Практически уроци

Създайте табло за обяснение на LIME с най-малко редове код

Сравнение на Flask, Plotly Dash и Streamlit за изграждане на табла за управление, които предоставят LIME обяснения за резултатите от класификацията

В по-ранна публикация описах как да обясня резултатите от фино зърнест класификатор на настроения с помощта на LIME ( Lлокален Iinterpretable Mmodel- агностиEчни обяснения). За да обобщим, следните шест модела бяха използвани за изготвяне на фини прогнози за клас на настроения в набора от данни Stanford Sentiment Treebank (SST-5).

  • Базирани на правила модели: TextBlob и VADER
  • Модели, базирани на функции: Логистична регресия и Поддържаща векторна машина
  • Базирани на вграждане модели: FastText и Flair

Използван е линеен работен процес за анализиране и обяснение на резултатите от класификацията на настроенията, използвайки всеки метод. Всеки модел беше обучен на 5 класа настроения (от 1 до 5), като 1 беше „силно негативен“, 3 бяха „неутрални“ и 5 бяха „силно положителни“.

Целта на тази публикация е да покаже как да изградите табло за обяснение (използвайки една от трите рамки), което приема обучен модел и извежда LIME обяснения за прогнозата, направена от модела.

Примерно обяснение на LIME

Казано просто, LIME генерира обект за обяснение, съдържащ визуализации (като вграден JavaScript), които могат да бъдат изведени в HTML файл, който след това може да бъде отворен във всеки браузър. Типичен изход от LIME е показан по-долу.

Защо да създадете приложение за интерактивно табло?

За да се обяснят резултатите на класификатор с помощта на LIME, може да е тромаво да се налага да се записват отделни HTML файлове всеки път, когато трябва да се направи обяснение. Интерактивното табло за управление, което приема информация от потребителя, е много ефективно средство за бързо преминаване през множество тестови проби в реално време, предоставяйки на потребителя незабавна обратна връзка. В допълнение, наличието на табло за управление позволява на нетехнически потребители (които могат или не могат да знаят как да изпълняват скриптове на Python) да могат да правят свои собствени LIME обяснения при поискване.

Следващите раздели показват как можем да изградим табла за управление на LIME, като използваме три различни рамки: Flask, Dash и Streamlit.

Обяснителен клас

За лесно препращане към методите за прогнозиране на всеки класификатор, обектно-ориентираният шаблон по-долу се прилага, за да се даде възможност за повторно използване на кода, наличен в репото GitHub на проекта. Накратко, дефиниран е клас на Python, който приема списъка с вариации, генериран от LIME (произволни текстови проби с празни токени), след което извеждаме вероятност за клас за всяка проба като масив Numpy.

След като се върнат вероятностите на класа за всяка вариация, това може да се подаде към класа LimeTextExplainer (показан по-долу). Активирането на bag-of-words ( bow) би означавало, че LIME не взема предвид реда на думите при генериране на варианти. Въпреки това, моделите FastText и Flair бяха обучени, като се има предвид съответно n-грамите и контекстното подреждане, така че за честно сравнение между моделите опцията за флаг bow е деактивирана за всички обяснения на SST-5.

Обектът exp, върнат от обяснителя на LIME, е чрез вътрешния за LIME метод explain_instance, който преобразува прогнозите на локалния линеен модел (в числена форма) във визуална, интерпретируема форма. След това това може да бъде изведено като HTML.

Разделите по-долу описват как да капсулирате всички тези функции в приложение за интерактивно табло.

Вариант 1: Колба

По-долу е показана версия на Flask на таблото за управление на обяснението на LIME. Потребителят въвежда част от текста, избира броя произволни проби, които да генерира за LIME, и след това избира от даден списък с класификатори, като използва падащото меню. Щракването върху бутона Explain results! след това генерира HTML обект с обяснение на LIME, който се изобразява в HTML вградена рамка.

Въпреки че Flask не е инструмент за табло за данни (това е уеб рамка WSGI, която започна като обвивка около Werkzeug и Jinja), той предоставя проста архитектура, базирана на плъгини, от която разработчиците могат да изграждат и разширяват интерфейси за сложни приложения. Ключовата сила на Flask е неговата устойчивост в производствена среда и многобройните разширения около него в екосистемата на Python.

За да създадете табло за управление на LIME за обяснение с помощта на Flask, е необходимо да знаете за следните части от технологията:

  • HTML/JavaScript: Цялостната структура и съдържание на страницата се определя с помощта на HTML. Всички действия, които трябва да бъдат задействани въз основа на стойността на полето или въведеното от потребителя, трябва да бъдат дефинирани с помощта на JavaScript, или чрез самия HTML файл, или заредени от външен източник.
  • CSS: Стиловете и оформлението на страницата се дефинират с помощта на CSS файл.
  • Jinja2: Това е машина за шаблони, която генерира динамично HTML кода на страницата от рамките на Python. Това е необходимо поради съображения за сигурност (неизползването на шаблони и предаването на неекраниран, статичен HTML може да доведе до атаки със скриптове между сайтове). Механизмът на шаблона се управлява от Python, а крайният HTML се изобразява с помощта на методите на Flask.

Приложение Flask: структура на директория

Структурата на директорията, използвана за приложението Flask, е показана по-долу. Необходимите стилове са конфигурирани с помощта на CSS във файла static/style.css, а HTML шаблонът, който трябва да се визуализира, е дефиниран в templates/index.html. Всички обучени модели на класификатор на настроения отиват в директорията models. Обяснителният клас е дефиниран в lime_explainer.py, а маршрутите на Flask в app.py.

За този случай на употреба кодът на приложението във Flask е написан по възможно най-простия начин. Дефинирани са два маршрута (маршрутът по подразбиране '/' и маршрутът за резултатите от LIME, 'result'). Имайте предвид, че маршрутът на резултатите използва POST заявка, което означава, че генерира HTML (чрез Jinja) само след като потребителят въведе някаква информация в приложението и взаимодейства с него.

Кодът за приложението за обяснение на Flask LIME е достъпен тук в GitHub:



Вариант 2: Тире

Алтернативен подход за проектиране на табло за управление на LIME е използването на библиотеката Dash на Plotly. Dash е рамка за изграждане на аналитични уеб приложения в Python. Ползите от използването на Dash са двойни: разработчиците могат да проектират приложения само с помощта на Python (не се изисква JavaScript) и имат пълен контрол върху дизайна и структурата на приложението чрез CSS. По-долу е демонстрирано приложение за обяснение на LIME, написано с Dash. Точно както в случая с приложението Flask, щракването върху бутона Explain results генерира HTML обект с обяснение на LIME, който се изобразява чрез обвивката на Dash около HTML iframes.

Приложение Dash: структура на директорията

Структурата на директорията, използвана за приложението Dash, е показана по-долу. Необходимите стилове са конфигурирани с помощта на CSS във файла assets/style.css. За разлика от примера с Flask, HTML оформлението на приложението и маршрутите/взаимодействията се дефинират с помощта на чист Python, в app.py. Всички обучени модели на класификатор на настроения отиват в директорията models. Обяснителният клас е дефиниран в lime_explainer.py.

Ключовите компоненти на кода на приложението Dash са описани по-долу. Първият е оформлението на приложението, което е написано на Python с помощта на HTML обвивките на Dash.

Често срещани HTML обекти като заглавки, етикети, въвеждане на текст и вградени рамки могат лесно да се добавят с помощта на конструкции на Python, както е показано.

Следващият компонент е обратното извикване, което е реактивен, функционален код, който позволява на разработчиците да наблюдават, променят и актуализират свойствата на всеки компонент в потребителския интерфейс. В Dash обратните извиквания се дефинират с помощта на синтаксиса на декоратора на Python. Обратните повиквания са изключително мощни начини за кодиране на интерактивност в приложение, тъй като те проследяват състояния при щраквания върху бутони, както и при актуализации на данни. Основното обратно извикване, използвано в обяснителя на LIME, е показано по-долу.

Съгласно горната конструкция, предаваме щракването на бутона на потребителя (или бутона „Изпращане“, или бутона „Изчистване“), както и състоянията на падащото меню, броя на пробите, въведени в текста вход и текстовата проба, за която искаме да предвидим настроението. Проследяването на състоянието (за разлика само от стойността) на всяко текстово поле тук е важно – то ни позволява да свържем изпълнението на обратното извикване с щракването върху бутона, вместо изпълнявайки го всеки път, когато се актуализира стойност във въведения текст.

Кодът за приложението за обяснение на Dash LIME също е наличен в GitHub:



Вариант 3: Streamlit

Друга алтернатива е да използвате Streamlit за изграждане на приложението за обяснение. Това е най-бързият подход, който изисква много основни познания за уеб разработка и най-малко редове код. За разлика от подходите на Flask и Dash, приложението Streamlit използва свои собствени стилове и оформление (не са възможни персонализации чрез CSS, поне с помощта на конвенционални средства). Приложението за обяснение Streamlit LIME е показано в действие по-долу.

Тъй като Streamlit е проектиран от самото начало, за да подпомага бързото създаване и споделяне на уеб приложения, приложението за табло за управление LIME има изключително проста структура на директория. Целият код за уеб приложението е написан в един файл, app.py - това включва джаджи, структура, взаимодействия и всички въведени от потребителя данни за правене на LIME прогнози. Забележителният аспект на този дизайн е, че дори с цялата тази функционалност, натъпкана в един файл, той все още е много кратък (~40 реда код!). В резултат на това ние използваме само отделни директории за специфични за приложението обекти, като модели и данни.

Целият код за таблото за управление Streamlit е показан по-долу.

Заглавките са написани в синтаксис за маркиране. Имайте предвид, че тъй като API на Streamlit е проектиран за бързина и лекота на използване, той не позволява лесен достъп до основния HTML, за разлика от Flask и Dash. В резултат на това от нас се изисква изрично да използваме опасно изобразяване на необработени HTML низове (с помощта на ключовата дума unsafe_allow_html), за да получим централно подравнени заглавки в този случай. След това HTML изходът от обяснителя на LIME се изобразява с помощта на Streamlit HTML компонент, който е персонализиран компонент, който показва HTML низа в iframe.

Както винаги, кодът за приложението за обяснение на Streamlit LIME е наличен в GitHub:



Разгръщане

За целите на тази публикация и трите приложения бяха внедрени с помощта на Heroku, PaaS система, която позволява на разработчиците да създават, изпълняват и управляват приложения в облака. Всяка от трите рамки, използвани за изграждане на приложението, има добри ръководства за внедряване на Heroku, показани по-долу.

Въпреки това също така е сравнително лесно да се разположат Flask или Dash приложения, като се използва производствен клас WSGI уеб сървър, като gunicorn и балансиращо натоварване като Nginx. По време на внедряването Nginx действа като обратен прокси, който се намира пред уеб сървъра, за да обработва голям брой заявки с висока степен на надеждност. По същия начин Streamlit също предлага средство за „ръчно внедряване на приложения“, използвайки комбинация от Docker и/или Nginx.

Бележка относно скалируемостта в уеб рамките на Python

Интерфейсът на шлюза на уеб сървъра (WSGI) е спецификация на Python, разработена като стандарт за уеб рамки на Python за взаимодействие с уеб сървъри. Наличието на такава система улеснява разработчиците да поставят услуга като Nginx пред уеб приложението на Python (напр. написано на Flask или Dash) като обратен прокси, който препраща всички заявки към уеб приложението. Ключово свойство на съвместимите с WSGI сървъри е, че те са синхронни. Това означава, че всяка заявка блокира сървъра, докато не получи отговор от приложението, наречено блокираща операция. Типичният начин, по който сървърите на WSGI включват мащабируемост, е чрез използването на многонишковост, при която се създава нова нишка за всяка заявка, за да могат да обработват множество заявки едновременно. След това това се комбинира с изпълнение на множество работни процеси на уеб сървъра, който се мащабира добре, но е ограничен от броя на наличните физически ядра на дадена машина.

Подходът WSGI, както се използва от рамки като Flask и Dash, може да ограничи по отношение на мащабирането, ако има много голям брой влизащи заявки. Начинът, по който това се решава в производствените системи, е чрез хоризонтално мащабиране >, т.е. добавяне на все повече и повече сървъри и използване на услуги за балансиране на натоварването като Nginx, които могат да разпределят равномерно натоварването между всички сървъри по време на големи обеми заявки.

Последните рамки за уеб приложения на Python, като Streamlit, вместо това разчитат изцяло на различна система за едновременност. Streamlit използва уеб сървър Tornado под капака, който е проектиран от самото начало да използва асинхронни цикли на събития. В тази система се използва една нишка, която реализира неблокиращи функции, които се изпълняват по ред на пристигане. Този подход може лесно да постигне много висока степен на едновременност в уеб приложението, което в приложения, които разчитат до голяма степен на I/O обвързани операции, наистина може да помогне за мащабиране на системата, за да обработва голям обем от заявки едновременно.

Както винаги, няма едно единствено правило, което да реши кой подход на едновременност е по-добър от другия. В зависимост от точния случай на използване и съответното приложение подходяща опция може да бъде услуга, базирана на WSGI или асинхронна услуга, управлявана от цикъл на събития.

Допълнително четене: WSGI вече не е достатъчен — Части I, II и III

Кога има най-голям смисъл да се използва всяка рамка?

Този раздел обсъжда ситуациите, в които всяка рамка е най-подходяща за поставената задача.

Колба

Силата на Flask се крие в способността му да позволи на разработчиците да използват всяка комбинация от предни инструменти за създаване на уеб приложение. Това включва разширения за въвеждане на формуляри, като WTForms и Flask-Login, както и библиотеки за визуализация на JavaScript (Highcharts или D3). Освен това Flask предоставя на разработчиците пълен достъп до основната структура на страницата и потребителските взаимодействия чрез HTML, CSS, jQuery и Bootstrap, позволявайки огромна гъвкавост при изграждането на много сложни приложения въз основа на изискванията на проекта.

По отношение на таблото за обяснение на LIME, показано в тази публикация, Flask е отлична опция за всеки един от следните сценарии:

  • Приложението е написано от екип с опит в JavaScript, HTML и CSS, както и различните методи за HTTP заявки (GET, POST и др.)
  • Приложението е част от много по-голямо табло за управление, захранвано от JavaScript рамка в предния край
  • Множество RESTful крайни точки, които обработват и обслужват данни, вече съществуват (след което LIME обяснителят може просто да бъде написан като друга крайна точка, подаваща към предния край)

Тире

Dash е страхотна опция за разработчици, които изискват висока степен на персонализация за своите приложения, докато работят основно в Python среда. Редица мощни предни инструменти за визуализация (от JavaScript библиотеката Plotly.js) се предоставят направо от кутията, което позволява на разработчиците да се съсредоточат основно върху стилизирането на своите приложения и добавянето на потребителски взаимодействия. Тъй като Dash е изграден върху Flask, той следва подобна стратегия за внедряване като тази на Flask, което го прави много лесен за използване от екипи, които вече имат опит с внедряването на Flask приложения в производството.

Като цяло, Dash е отлична опция за изграждане на табло за управление на LIME обяснител във всеки един от следните сценарии:

  • Приложението трябва да бъде написано, за да се интегрира със съществуващо приложение на Flask
  • Екипът, който разработва и внедрява приложението, има опит в Python (но не толкова в JavaScript)
  • Необходима е добра степен на персонализиране за таблото за управление (което позволява Dash, като предоставя на разработчиците достъп до основния CSS)

Осветен от поток

Като сравнително новодошъл в екосистемата, Streamlit блести в ситуации, в които учените по данни трябва бързо да споделят работата си с по-голям екип чрез интерактивно приложение. Освен това работи страхотно за отделен учен по данни за бързо и интерактивно изследване на набор от данни или ефективността на модел върху отделни проби.

За таблото за управление на обяснителя на LIME Streamlit е чудесна алтернатива за използване във всеки от следните сценарии:

  • Приложението е написано от екип (или индивид) с минимален опит в уеб разработката
  • Приложението трябва да бъде изградено бързо за най-малко време и с възможно най-малко редове код
  • Разработчиците искат да отделят повече време за изграждане на интерактивни инструменти и възможно най-малко време за персонализиране на външния вид на приложението

Изводи

Тази публикация подчерта три различни подхода за изграждане на приложение за интерактивно табло за обяснение на LIME. Streamlit е най-малко многословният и най-лесният за научаване сред всички опции. Flask изисква най-предварителна инвестиция във време, по отношение на изучаването на различните части, които се вписват заедно (HTML, CSS, jQuery/JavaScript, Jinja2 и методи за HTTP заявки). Plotly Dash стои добре между Flask и Streamlit, по отношение на сложност и първоначални усилия да стартирате таблото за управление. В зависимост от състава и набора от умения на екипа, който предприема такъв проект, всяка от трите опции може да бъде най-подходяща.

Основната причина да се създаде табло за управление на LIME, както е показано, е да се позволи на хора, които не са специалисти по данни, да изследват резултатите от NLP класификатора. Осигуряването на интерактивни средства за тестване на резултатите от отделна проба в движение може да помогне за диагностицирането на проблеми с НЛП моделите и да подобри интерпретируемостта на модела, поне до известна степен. Забавлявайте се, играейки и персонализирайки кода от всяко репо (показано по-долу) за вашия собствен случай на употреба!

Първоначално публикувано на адрес https://prrao87.github.io на 24 октомври 2020 г.