データセット
変換されたセットが使用されました。reuters-22000レコード 、 watson-th-530レコード 、 さらに1つのwatson-th-50レコード 。 ちなみに、私はコメント/ドラッグに投げ込まれたロシア語のテキストのセットを拒否しません(ただし、コメントに入れたほうが良いでしょう)。
ネットワーク機器
ここで説明されたネットワークの 1つの実装に基づいて。 githubで使用される実装のコード 。
私の場合、ネットワークの入力にワードベクトルがあります(word2vecのgensim実装が使用されます)。 ネットワーク構造は次のとおりです。

要するに:
- テキストは、word_count x word_vector_sizeの形式のマトリックスとして表されます。 個々の単語のベクトルはword2vecからのもので、たとえばこの投稿で読むことができます。 ユーザーがどのテキストを手のひらでオフにするかは事前にわからないので、長さ2 * Nを取ります。ここで、Nはトレーニングセットの最も長いテキストのベクトルの数です。 はい、指を空に突きました。
- マトリックスは、ネットワークの畳み込みセクションによって処理されます(出力では、単語の変換された特徴を取得します)
- 選択された機能は、完全に接続されたネットワークセクションによって処理されます。
最初に単語のストップをフィルタリングします(reuter-mデータセットには影響しませんでしたが、小さなセットでは効果がありました)。 以下について。
Windowsに必要なソフトウェア(keras / theano、cuda)をインストールする
Linuxへのインストールは非常に簡単でした。 必須:
- python3.5
- pythonヘッダーファイル(debianのpython-dev)
- gcc
- クーダ
- pythonライブラリは以下のリストと同じです
win10 x64の場合、おおよそのシーケンスは次のとおりです。
- python3.5を使用したAnaconda 。
- Cuda 8.0 CPUで実行できます(gccで十分であり、次の4つのステップは不要です)が、比較的大きなデータセットでは速度の低下が著しいはずです(チェックしませんでした)。
- nvccへのパスがPATHに追加されました(そうでない場合、theanoはそれを検出しません)。
- Windows 10キット(corecrt.hが必要)を含むVisual Studio 2015とC ++。
- cl.exeへのパスがPATHに追加されました。
- INCLUDEのcorecrt.hへのパス(私の場合、C:\ Program Files(x86)\ Windows Kits \ 10 \ Include \ 10.0.10240.0 \ ucrt)。
-
conda install mingw libpython
グリッドのコンパイル時にgccとlibpythonが必要になります。 - さて、
pip install keras theano python-levenshtein gensim nltk
(pip install keras theano python-levenshtein gensim nltk
からkeras-thバックエンドをテンソルフローに置き換えることから始めるかもしれませんが、私はそれをテストしていません)。 - .theanorcでは、gccに次のフラグが指定されています。
[gcc] cxxflags = -D_hypot=hypot
- Pythonを実行して実行する
import nltk nltk.download()
ワープロ
この段階では、「ホワイトリスト」(以下のリスト)と残りのリストの組み合わせに含まれていないストップワードの削除がベクトル化されます。 適用されたアルゴリズムの入力データ:
- 言語-ストップワードのリストをトークン化して返すには、nltkが必要です
- ストップワードを使用する単語の組み合わせの「ホワイトリスト」。 たとえば、「on」はストップワードに起因しますが、[「turn」、「on」]は別の問題です。
- ベクトルword2vec
アルゴリズム(少なくとも2つの改善が見られるが、マスターされていない):
- 入力テキストをntlk.tokenizeトークンに分割します(条件付き-「Hello、world!」は[「hello」、「、」、「world」、「!」]に変換されます)。
- word2vec辞書にないトークンをドロップします。
実際には、それらは存在せず、同様の距離を強調することはできませんでした。 これまでのところ、レーベンシュタイン距離のみ、ベクトルからトレーニングセットに含まれるベクトルまでの距離に応じて、レーベンシュタイン距離が最小のトークンをフィルタリングするという考えがあります。
- トークンを選択:
- ストップワードのリストには含まれていません(天気データセットのエラーを減らしましたが、次のステップはありません-「car_intents」の結果は本当に台無しになりました)。
- トークンがストップワードリストにある場合、トークンが存在するテキスト内のホワイトリストシーケンスの出現を確認します(条件付き-「オン」を見つけることにより、リスト[["turn"、 "on"]]からシーケンスの存在を確認します)。 ある場合-まだ追加します。 改善すべき点があります-現在、この例では「ターン」の存在を確認していますが、この「オン」にも当てはまらない場合があります。
- ストップワードのリストには含まれていません(天気データセットのエラーを減らしましたが、次のステップはありません-「car_intents」の結果は本当に台無しになりました)。
- 選択したトークンをベクターに置き換えます。
私たちへのコード、コード
実際、変更の影響を評価したコード
import itertools import json import numpy from gensim.models import Word2Vec from pynlc.test_data import reuters_classes, word2vec, car_classes, weather_classes from pynlc.text_classifier import TextClassifier from pynlc.text_processor import TextProcessor from sklearn.metrics import mean_squared_error def classification_demo(data_path, train_before, test_before, train_epochs, test_labels_path, instantiated_test_labels_path, trained_path): with open(data_path, 'r', encoding='utf-8') as data_source: data = json.load(data_source) texts = [item["text"] for item in data] class_names = [item["classes"] for item in data] train_texts = texts[:train_before] train_classes = class_names[:train_before] test_texts = texts[train_before:test_before] test_classes = class_names[train_before:test_before] text_processor = TextProcessor("english", [["turn", "on"], ["turn", "off"]], Word2Vec.load_word2vec_format(word2vec)) classifier = TextClassifier(text_processor) classifier.train(train_texts, train_classes, train_epochs, True) prediction = classifier.predict(test_texts) with open(test_labels_path, "w", encoding="utf-8") as test_labels_output: test_labels_output_lst = [] for i in range(0, len(prediction)): test_labels_output_lst.append({ "real": test_classes[i], "classified": prediction[i] }) json.dump(test_labels_output_lst, test_labels_output) instantiated_classifier = TextClassifier(text_processor, **classifier.config) instantiated_prediction = instantiated_classifier.predict(test_texts) with open(instantiated_test_labels_path, "w", encoding="utf-8") as instantiated_test_labels_output: instantiated_test_labels_output_lst = [] for i in range(0, len(instantiated_prediction)): instantiated_test_labels_output_lst.append({ "real": test_classes[i], "classified": instantiated_prediction[i] }) json.dump(instantiated_test_labels_output_lst, instantiated_test_labels_output) with open(trained_path, "w", encoding="utf-8") as trained_output: json.dump(classifier.config, trained_output, ensure_ascii=True) def classification_error(files): for name in files: with open(name, "r", encoding="utf-8") as src: data = json.load(src) classes = [] real = [] for row in data: classes.append(row["real"]) classified = row["classified"] row_classes = list(classified.keys()) row_classes.sort() real.append([classified[class_name] for class_name in row_classes]) labels = [] class_names = list(set(itertools.chain(*classes))) class_names.sort() for item_classes in classes: labels.append([int(class_name in item_classes) for class_name in class_names]) real_np = numpy.array(real) mse = mean_squared_error(numpy.array(labels), real_np) print(name, mse) if __name__ == '__main__': print("Reuters:\n") classification_demo(reuters_classes, 10000, 15000, 10, "reuters_test_labels.json", "reuters_car_test_labels.json", "reuters_trained.json") classification_error(["reuters_test_labels.json", "reuters_car_test_labels.json"]) print("Car intents:\n") classification_demo(car_classes, 400, 500, 20, "car_test_labels.json", "instantiated_car_test_labels.json", "car_trained.json") classification_error(["cars_test_labels.json", "instantiated_cars_test_labels.json"]) print("Weather:\n") classification_demo(weather_classes, 40, 50, 30, "weather_test_labels.json", "instantiated_weather_test_labels.json", "weather_trained.json") classification_error(["weather_test_labels.json", "instantiated_weather_test_labels.json"])
ここに表示されます:
- データ準備:
with open(data_path, 'r', encoding='utf-8') as data_source: data = json.load(data_source) texts = [item["text"] for item in data] class_names = [item["classes"] for item in data] train_texts = texts[:train_before] train_classes = class_names[:train_before] test_texts = texts[train_before:test_before] test_classes = class_names[train_before:test_before]
- 新しい分類子の作成:
text_processor = TextProcessor("english", [["turn", "on"], ["turn", "off"]], Word2Vec.load_word2vec_format(word2vec)) classifier = TextClassifier(text_processor)
- 彼のトレーニング:
classifier.train(train_texts, train_classes, train_epochs, True)
- テストサンプルのクラスを予測し、「実際のクラス」-「予測クラス確率」のペアを保存します。
prediction = classifier.predict(test_texts) with open(test_labels_path, "w", encoding="utf-8") as test_labels_output: test_labels_output_lst = [] for i in range(0, len(prediction)): test_labels_output_lst.append({ "real": test_classes[i], "classified": prediction[i] }) json.dump(test_labels_output_lst, test_labels_output)
- 構成による分類子の新しいインスタンスの作成(dict、たとえばjsonでシリアル化/逆シリアル化できます):
instantiated_classifier = TextClassifier(text_processor, **classifier.config)
排気はおよそ次のとおりです。
C:\Users\user\pynlc-env\lib\site-packages\gensim\utils.py:840: UserWarning: detected Windows; aliasing chunkize to chunkize_serial warnings.warn("detected Windows; aliasing chunkize to chunkize_serial") C:\Users\user\pynlc-env\lib\site-packages\gensim\utils.py:1015: UserWarning: Pattern library is not installed, lemmatization won't be available. warnings.warn("Pattern library is not installed, lemmatization won't be available.") Using Theano backend. Using gpu device 0: GeForce GT 730 (CNMeM is disabled, cuDNN not available) Reuters: Train on 3000 samples, validate on 7000 samples Epoch 1/10 20/3000 [..............................] - ETA: 307s - loss: 0.6968 - acc: 0.5376 .... 3000/3000 [==============================] - 640s - loss: 0.0018 - acc: 0.9996 - val_loss: 0.0019 - val_acc: 0.9996 Epoch 8/10 20/3000 [..............................] - ETA: 323s - loss: 0.0012 - acc: 0.9994 ... 3000/3000 [==============================] - 635s - loss: 0.0012 - acc: 0.9997 - val_loss: 9.2200e-04 - val_acc: 0.9998 Epoch 9/10 20/3000 [..............................] - ETA: 315s - loss: 3.4387e-05 - acc: 1.0000 ... 3000/3000 [==============================] - 879s - loss: 0.0012 - acc: 0.9997 - val_loss: 0.0016 - val_acc: 0.9995 Epoch 10/10 20/3000 [..............................] - ETA: 327s - loss: 8.0144e-04 - acc: 0.9997 ... 3000/3000 [==============================] - 655s - loss: 0.0012 - acc: 0.9997 - val_loss: 7.4761e-04 - val_acc: 0.9998 reuters_test_labels.json 0.000151774189194 reuters_car_test_labels.json 0.000151774189194 Car intents: Train on 280 samples, validate on 120 samples Epoch 1/20 20/280 [=>............................] - ETA: 0s - loss: 0.6729 - acc: 0.5250 ... 280/280 [==============================] - 0s - loss: 0.2914 - acc: 0.8980 - val_loss: 0.2282 - val_acc: 0.9375 ... Epoch 19/20 20/280 [=>............................] - ETA: 0s - loss: 0.0552 - acc: 0.9857 ... 280/280 [==============================] - 0s - loss: 0.0464 - acc: 0.9842 - val_loss: 0.1647 - val_acc: 0.9494 Epoch 20/20 20/280 [=>............................] - ETA: 0s - loss: 0.0636 - acc: 0.9714 ... 280/280 [==============================] - 0s - loss: 0.0447 - acc: 0.9849 - val_loss: 0.1583 - val_acc: 0.9530 cars_test_labels.json 0.0520754688092 instantiated_cars_test_labels.json 0.0520754688092 Weather: Train on 28 samples, validate on 12 samples Epoch 1/30 20/28 [====================>.........] - ETA: 0s - loss: 0.6457 - acc: 0.6000 ... Epoch 29/30 20/28 [====================>.........] - ETA: 0s - loss: 0.0021 - acc: 1.0000 ... 28/28 [==============================] - 0s - loss: 0.0019 - acc: 1.0000 - val_loss: 0.1487 - val_acc: 0.9167 Epoch 30/30 ... 28/28 [==============================] - 0s - loss: 0.0018 - acc: 1.0000 - val_loss: 0.1517 - val_acc: 0.9167 weather_test_labels.json 0.0136964029149 instantiated_weather_test_labels.json 0.0136964029149
ストップワードを使用した実験の過程で:
- ロイターセットのエラーは、ストップワードの削除/保存に関係なく同等のままでした。
- 天気のエラー-ストップワードを削除するときの8%から落ちました。 アルゴリズムの複雑さは影響しませんでした(ストップワードを保存する必要のある組み合わせがないため)。
- car_intentのエラー-ストップワードの削除時に約15%に増加しました(たとえば、条件付きの「オン」が「ターン」に切り捨てられました)。 「ホワイトリスト」の処理を追加する場合-前のレベルに戻ります。
事前に訓練された分類器を実行する例
実際、TextClassifier.configプロパティは、たとえばjsonでレンダリングでき、jsonから復元された後、その要素をTextClassifierコンストラクターに渡すことができる辞書です。 例:
import json from gensim.models import Word2Vec from pynlc.test_data import word2vec from pynlc import TextProcessor, TextClassifier if __name__ == '__main__': text_processor = TextProcessor("english", [["turn", "on"], ["turn", "off"]], Word2Vec.load_word2vec_format(word2vec)) with open("weather_trained.json", "r", encoding="utf-8") as classifier_data_source: classifier_data = json.load(classifier_data_source) classifier = TextClassifier(text_processor, **classifier_data) texts = [ "Will it be windy or rainy at evening?", "How cold it'll be today?" ] predictions = classifier.predict(texts) for i in range(0, len(texts)): print(texts[i]) print(predictions[i])
そして彼の排気:
C:\Users\user\pynlc-env\lib\site-packages\gensim\utils.py:840: UserWarning: detected Windows; aliasing chunkize to chunkize_serial warnings.warn("detected Windows; aliasing chunkize to chunkize_serial") C:\Users\user\pynlc-env\lib\site-packages\gensim\utils.py:1015: UserWarning: Pattern library is not installed, lemmatization won't be available. warnings.warn("Pattern library is not installed, lemmatization won't be available.") Using Theano backend. Will it be windy or rainy at evening? {'temperature': 0.039208538830280304, 'conditions': 0.9617446660995483} How cold it'll be today? {'temperature': 0.9986168146133423, 'conditions': 0.0016815820708870888}
はい、ロイターのデータセットでトレーニングされたネットワーク構成はこちらです。 19Mbデータセットのメッシュのギガバイト、はい:-)