企业网站制作多少钱,青岛网站制作公司网络,洛阳青峰网络科技有限公司,seo网站建设微点击上方关注#xff0c;All in AI中国上周#xff0c;我看了一个关于“NLP的实践特性工程”的演讲。主要是关于LIME和SHAP在文本分类可解释性方面是如何工作的。我决定写一篇关于它们的文章#xff0c;因为它们很有趣、易于使用#xff0c;而且视觉上很吸引人。所有的机器…点击上方关注All in AI中国上周我看了一个关于“NLP的实践特性工程”的演讲。主要是关于LIME和SHAP在文本分类可解释性方面是如何工作的。我决定写一篇关于它们的文章因为它们很有趣、易于使用而且视觉上很吸引人。所有的机器学习模型都是在更高的维度上运行的而不是在人脑可以直接看到的维度上运行的这些机器学习模型都可以被称为黑盒模型它可以归结为模型的可解释性。特别是在NLP领域中特征的维数往往很大说明特征的重要性变得越来越复杂。LIME SHAP不仅帮助我们向最终用户解释NLP模型的工作原理而且帮助我们自己解释NLP模型是如何工作的。利用 Stack Overflow 问题标签分类数据集我们将构建一个多类文本分类模型然后分别应用LIME和SHAP对模型进行解释。由于我们之前已经做过多次文本分类所以我们将快速构建NLP模型并着重于模型的可解释性。数据预处理、特征工程和逻辑回归 import pandas as pdimport numpy as npimport sklearnimport sklearn.ensembleimport sklearn.metricsfrom sklearn.utils import shufflefrom __future__ import print_functionfrom io import StringIOimport refrom bs4 import BeautifulSoupfrom nltk.corpus import stopwordsfrom sklearn.model_selection import train_test_splitfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_score, f1_score, precision_score, recall_scoreimport limefrom lime import lime_textfrom lime.lime_text import LimeTextExplainerfrom sklearn.pipeline import make_pipelinedf pd.read_csv(stack-overflow-data.csv)df df[pd.notnull(df[tags])]df df.sample(frac0.5, random_state99).reset_index(dropTrue)df shuffle(df, random_state22)df df.reset_index(dropTrue)df[class_label] df[tags].factorize()[0]class_label_df df[[tags, class_label]].drop_duplicates().sort_values(class_label)label_to_id dict(class_label_df.values)id_to_label dict(class_label_df[[class_label, tags]].values)REPLACE_BY_SPACE_RE re.compile([/(){}[]|,;])BAD_SYMBOLS_RE re.compile([^0-9a-z #_])# STOPWORDS set(stopwords.words(english))def clean_text(text): text: a string return: modified initial string text BeautifulSoup(text, lxml).text # HTML decoding. BeautifulSoups text attribute will return a string stripped of any HTML tags and metadata. text text.lower() # lowercase text text REPLACE_BY_SPACE_RE.sub( , text) # replace REPLACE_BY_SPACE_RE symbols by space in text. substitute the matched string in REPLACE_BY_SPACE_RE with space. text BAD_SYMBOLS_RE.sub(, text) # remove symbols which are in BAD_SYMBOLS_RE from text. substitute the matched string in BAD_SYMBOLS_RE with nothing. # text .join(word for word in text.split() if word not in STOPWORDS) # remove stopwors from text return textdf[post] df[post].apply(clean_text)list_corpus df[post].tolist()list_labels df[class_label].tolist()X_train, X_test, y_train, y_test train_test_split(list_corpus, list_labels, test_size0.2, random_state40)vectorizer CountVectorizer(analyzerword,token_patternrw{1,}, ngram_range(1, 3), stop_words english, binaryTrue)train_vectors vectorizer.fit_transform(X_train)test_vectors vectorizer.transform(X_test)logreg LogisticRegression(n_jobs1, C1e5)logreg.fit(train_vectors, y_train)pred logreg.predict(test_vectors)accuracy accuracy_score(y_test, pred)precision precision_score(y_test, pred, averageweighted)recall recall_score(y_test, pred, averageweighted)f1 f1_score(y_test, pred, averageweighted)print(accuracy %.3f, precision %.3f, recall %.3f, f1 %.3f % (accuracy, precision, recall, f1))我们现在目标并不是产生最好的结果。我想尽快进入LIME SHAP这就是接下来发生的事情。用LIME解释文本预测从现在开始这是有趣的部分。下面的代码片段主要是从LIME教程中借来的。c make_pipeline(vectorizer, logreg)class_nameslist(df.tags.unique())explainer LimeTextExplainer(class_namesclass_names)idx 1877exp explainer.explain_instance(X_test[idx], c.predict_proba, num_features6, labels[4, 8])print(Document id: %d % idx)print(Predicted class , class_names[logreg.predict(test_vectors[idx]).reshape(1,-1)[0,0]])print(True class: %s % class_names[y_test[idx]])我们在测试集中随机选择一个文档它恰好是一个标记为sql的文档我们的模型也预测它是sql。使用这个文档我们为标签4 (sql)和标签8 (python)生成解释。print (Explanation for class %s % class_names[4])print (.join(map(str, exp.as_list(label4))))print (Explanation for class %s % class_names[8])print (.join(map(str, exp.as_list(label8))))很明显这个文档对标签sql有最高的解释。我们还注意到正负号与特定的标签有关例如单词sql对类sql是正的而对类python是负的反之亦然。我们要为这个文档生成2类标签顶部。exp explainer.explain_instance(X_test[idx], c.predict_proba, num_features6, top_labels2)print(exp.available_labels())它给出了sql和python。exp.show_in_notebook(textFalse)让我来解释一下这种可视化:1. 对于本文档词 sql对于类sql具有最高的正分数。2. 我们的模型预测该文档应该标记为sql其概率为100%。3. 如果我们从文档中删除wordsql我们期望模型预测label sql的概率为100% - 65% 35%。4. 另一方面单词sql对于类python是负面的我们的模型已经了解到单词range对于类python有一个小的正面得分。我们可能想放大并研究类sql的解释以及文档本身。exp.show_in_notebook(texty_test[idx], labels(4,))使用SHAP解释文本预测以下过程是从本教程中学到的。「链接」from sklearn.preprocessing import MultiLabelBinarizerimport tensorflow as tffrom tensorflow.keras.preprocessing import textimport keras.backend.tensorflow_backend as KK.set_sessionimport shaptags_split [tags.split(,) for tags in df[tags].values]tag_encoder MultiLabelBinarizer()tags_encoded tag_encoder.fit_transform(tags_split)num_tags len(tags_encoded[0])train_size int(len(df) * .8)y_train tags_encoded[: train_size]y_test tags_encoded[train_size:]class TextPreprocessor(object): def __init__(self, vocab_size): self._vocab_size vocab_size self._tokenizer None def create_tokenizer(self, text_list): tokenizer text.Tokenizer(num_words self._vocab_size) tokenizer.fit_on_texts(text_list) self._tokenizer tokenizer def transform_text(self, text_list): text_matrix self._tokenizer.texts_to_matrix(text_list) return text_matrixVOCAB_SIZE 500train_post df[post].values[: train_size]test_post df[post].values[train_size: ]processor TextPreprocessor(VOCAB_SIZE)processor.create_tokenizer(train_post)X_train processor.transform_text(train_post)X_test processor.transform_text(test_post)def create_model(vocab_size, num_tags): model tf.keras.models.Sequential() model.add(tf.keras.layers.Dense(50, input_shape (VOCAB_SIZE,), activationrelu)) model.add(tf.keras.layers.Dense(25, activationrelu))model.add(tf.keras.layers.Dense(num_tags, activationsigmoid)) model.compile(loss binary_crossentropy, optimizeradam, metrics [accuracy]) return model model create_model(VOCAB_SIZE, num_tags)model.fit(X_train, y_train, epochs 2, batch_size128, validation_split0.1) print(Eval loss/accuracy:{}.format(model.evaluate(X_test, y_test, batch_size 128)))模型训练完成后我们使用前200个训练文档作为背景数据集进行集成并创建一个SHAP explainer对象。我们在测试集的子集上获得各个预测的属性值。将索引转换为单词。使用SHAP的summary_plot方法来显示影响模型预测的主要特性。attrib_data X_train[:200]explainer shap.DeepExplainer(model, attrib_data)num_explanations 20shap_vals explainer.shap_values(X_test[:num_explanations])words processor._tokenizer.word_indexword_lookup list()for i in words.keys(): word_lookup.append(i)word_lookup [] word_lookupshap.summary_plot(shap_vals, feature_namesword_lookup, class_namestag_encoder.classes_)单词want是我们模型使用的最大信号词对类jquery预测贡献最大。单词php是我们模型使用的第四大信号词当然对PHP类贡献最大。另一方面单词php可能对另一个类有负面信号因为它不太可能在python文档中看到单词php。关于LIME SHAP的机器学习可解释性还有很多需要学习的地方。我只介绍了一小部分NLP。其余的可以在Github上找到。NLP-with-Python/LIME_SHAP_StackOverflow.ipynb at master · susanli2016/NLP-with-Python · GitHub