Google Search Console の
先日Google Search Console のLinearSVC
をRandomForestClassifier
を
前提
入力データ Search Analytics for Sheets - Google スプレッドシート アドオン で、
データを Google スプレッドシートに Export。
Export 後のスプレッドシートを CSV化した データを 入力データと しています。
Search Analytics for Sheets - Google スプレッドシート アドオン の使い方は、
サーチコンソールの詳細データを Googleスプレッドシートに 自動反映させてTableauに インポートする 方法 :: 「清水 誠」公式サイト
が参考に なりました。 学習データ
入力データの一部の キーワードを 切り出し、 別シートに 貼り付け、 人力で 800キーワードくらいを 分類しました。
それを、tsv 出力した ものを 学習データと しています。
以下、学習データと して 作成した tsv
を一部抜粋し テーブル形式に 変換した ものを 記載します。
Query | label_name |
---|---|
sonarqube | sonarqube |
no module named | python |
(1_8.w001) the standalone template_* settings were deprecated in django 1.8 | django |
//nosonar | sonarqube |
404 エラー | 404 |
404エラー | 404 |
404エラーページ | 404 |
先日実施したtsv
を
面倒に
をgspread
を
参考
以下、
Grid Search の
使い 方 scikit-learnで 最適な パラメータを 決める ために Grid Searchを 使う | tatsushim’s blog パラメータの
判断方法 不均衡な データの 分類問題に ついて with Python | か ものはしの 分析ブログ gensimsの
使い 方 k-means法で 文書の クラスタリング - Qiita BoW+SVMで 文書分類(1) | developer’s blog ランダムフォレストの
使い 方 Lec86_決定木と ランダ ムフォレスト
R vs Python:データ解析を比較 | プログラミング | POSTD
Python とR の 違い (ランダムフォレスト法) – Python で データサイエンス
クラス分類の 手順
以下の
クラスタリングには、sklearn
のRandomForestClassifier
を
クラスタ数の 決定
RandomForestClassifier
の
GridSearch
と
それを
prameter の
指定。 GridSearch
実行。best_estimator_
の値を 出力。
クラス分類
Google スプレッドシートの
学習データを TSV
にして 読み込み、 キーワードを 抽出。 サーチコンソールからの
取得結果の Google スプレッドシートを TSV
にして 読み込み、 キーワードを 抽出。 学習データと、
サーチコンソールからの 取得結果の キーワードを マージ、 キーワード内の 単語の 出現頻度を 数えて、 結果を 素性ベクトル化する。
2
[2]gensimを使います。 次元数削減が できるので キーワードが 増えても 次元数が 増えない ためです。 RandomForestClassifier
で学習 TSV
をクラス分類して、 スコアを 取得、 確からしさが 低い データに ついては、 分類結果の ラベルは 付与せず、 unknown
ラベルに置換 結果を、
Google スプレッドシートに 書き出す。
各種ライブラリの インストール
必要な
pip install sklearn numpy scipy pandas gensim
以下の
pip list | grep -e sklearn -e numpy -e scipy -e pandas -e gensim --------------------------- gensim (2.1.0) numpy (1.12.1) pandas (0.20.1) scipy (0.19.0) sklearn (0.0) ---------------------------
sudo pip install --upgrade gensim
実装
以下、
search_console_random_forest_classsifier.py
# -*- coding: utf-8 - from __future__ import print_function import numpy as np import search_console_classifier_utils as utils from gensim import corpora, models from gensim import matutils from sklearn.ensemble import RandomForestClassifier def get_max_label(array, score): index = 0 max_value = 0 for i in range(len(array)): item = array[i] if max_value < item: max_value = item index = i return {score[index]: max_value} def vec2dense(vec, num_terms): return list(matutils.corpus2dense([vec], num_terms=num_terms).T[0]) def create_keywords_data(): keywords = [] # 学習データからキーワードを取得 for line in utils.read_from_learning_tsv(0): keywords.append(utils.split_keyword(line)) # CSVからキーワードを取得 for line in utils.parse_report_tsv(): keywords.append(utils.split_keyword(line)) dictionary = corpora.Dictionary(keywords) corpus = [] for text in keywords: corpus.append(dictionary.doc2bow(text)) # 300次元に圧縮 lsi_model = models.LsiModel(corpus, id2word=dictionary, num_topics=300) lsi_corpus = lsi_model[corpus] denses = [vec2dense(lsi_corpus_elem, len(dictionary)) for lsi_corpus_elem in lsi_corpus] # 学習データ部のみ抽出 learning_denses = denses[:len(utils.read_from_learning_tsv(0))] # データに対応したラベルを取得 learning_labels = np.array(utils.read_from_learning_tsv(1)) return denses, learning_denses, learning_labels ######################### # クラスタ数の決定 # GridSearch実行 def execute_grid_search(): # 学習データ、Label の取得、作成 denses, learning_denses, learning_labels = create_keywords_data() # ------------------------------------- # RandomForestClassifierに学習データを入力、分類する # -------------------------------- # GridSearch のパラメータを設定 # 1. prameter の 指定。 parameters = { 'n_estimators': [5, 10, 20, 30, 50, 100, 300], 'max_features': [3, 5, 10, 15, 20], 'random_state': [0], 'n_jobs': [1], 'min_samples_split': [3, 5, 10, 15, 20, 25, 30, 40, 50, 100], 'max_depth': [3, 5, 10, 15, 20, 25, 30, 40, 50, 100] } # 2. `GridSearch` 実行。 from sklearn.model_selection import GridSearchCV clf = GridSearchCV(RandomForestClassifier(), parameters) clf.fit(learning_denses, learning_labels) # 3. `best_estimator_` の値を出力。 print("---------------------------") print(clf.best_estimator_) print("---------------------------") # メインメソッド def execute(): # 学習データ、Label の取得、作成 # ---------------------------------------------------------------------------- # 3. 学習データと、サーチコンソールからの取得結果のキーワードをマージ、キーワード内の単語の出現頻度を数えて、結果を素性ベクトル化する。 # ---------------------------- denses, learning_denses, learning_labels = create_keywords_data() # ---------------------------------------------------------------------------- # 4. `RandomForestClassifier` で学習 # ---------------------------- # 素の呼び出し # model = RandomForestClassifier() # GridSearch の結果得られた値を設定 model = RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=20, max_features=20, max_leaf_nodes=None, min_impurity_split=1e-07, min_samples_leaf=1, min_samples_split=5, min_weight_fraction_leaf=0.0, n_estimators=300, n_jobs=1, oob_score=False, random_state=0, verbose=0, warm_start=False) model.fit(learning_denses, learning_labels) classes = model.classes_ # ---------------------------------------------------------------------------- # 5. `TSV` をクラス分類して、スコアを取得、確からしさが低いデータについては、分類結果のラベルは付与せず、`unknown` ラベルに置換 # ---------------------------- scores = model.predict_proba(denses[len(utils.read_from_learning_tsv(0)):]) labels = [] for score in scores: max_dict = get_max_label(score, classes) for k, v in max_dict.items(): if v > 0.5: # 0.50 より大きい場合、ラベルを設定 labels.append(k) else: # 上記以外の場合は、"unknown" labels.append("unknown") # スプレッドシート更新 # ---------------------------------------------------------------------------- # 6. 結果を、Google スプレッドシートに書き出す。 # ---------------------------- utils.update_labels(labels) if __name__ == '__main__': # execute_grid_search() execute()
search_console_classifier_utils.py
以下、
Google Spread Sheet への
# -*- coding: utf-8 - import gspread from __builtin__ import unicode from oauth2client.service_account import ServiceAccountCredentials from sets import Set stop_words = Set(['name', 'not', 'the', 'usr', 'you', 'version', 'this']) scope = ['https://spreadsheets.google.com/feeds'] # stop word のチェック # 2文字以下の文字列、クラスタリングした結果、 # ラベルとして、出力されたあまり意味のわからない単語を除外 def __check_stop_word(word): if word in stop_words: return False if len(word) <= 2: return False return True # キーワードを区切る def split_keyword(text): keywords = text.split(" ") return [keyword for keyword in keywords if __check_stop_word(keyword)] # ストップワードを除外する def exclude_stop_words(text): return " ".join(split_keyword) # report csv を parse する def parse_report_tsv(): lines = [] row_count = 1 credentials = ServiceAccountCredentials.from_json_keyfile_name('your_api_key.json', scope) gc = gspread.authorize(credentials) # Google Search Consoleのデータは"Merge"シートに入力しています。 wks = gc.open("Google Search Console Analyze").worksheet("Merge") for line in wks.export(format='tsv').split("\n"): if row_count != 1: arr = line.split("\t") # キーワードカラムを取り出す lines.append(arr[1]) row_count += 1 return lines # learning_tsv parseする def read_from_learning_tsv(index): lines = [] row_count = 1 credentials = ServiceAccountCredentials.from_json_keyfile_name('your_api_key.json', scope) gc = gspread.authorize(credentials) # 学習データはシート名"LearningData"で入力しています。 wks = gc.open("Google Search Console Analyze").worksheet("LearningData") for line in wks.export(format='tsv').split("\n"): if row_count != 1: arr = line.split("\t") # キーワードカラムを取り出す lines.append(arr[index]) row_count += 1 return lines def update_labels(labels): # CSVを再度読み込み、ラベル名を追加して、CSV書き出し credentials = ServiceAccountCredentials.from_json_keyfile_name('your_api_key.json', scope) gc = gspread.authorize(credentials) wks = gc.open("Google Search Console Analyze").worksheet("Merge") # Select a range labels.insert(0, "Label") cell_list = wks.range('J1:J' + str(len(labels))) for i in range(len(labels)): cell_list[i].value = unicode(labels[i], 'utf-8') wks.update_cells(cell_list)
説明 クラスタ数の 決定
execute_grid_search
メソッド で
パラメータ指定部は、
得られたexecute
メソッドで
clf.best_estimator_
を
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=25, max_features=20, max_leaf_nodes=None, min_impurity_split=1e-07, min_samples_leaf=1, min_samples_split=3, min_weight_fraction_leaf=0.0, n_estimators=300, n_jobs=1, oob_score=False, random_state=0, verbose=0, warm_start=False)
クラス分類
以下、説明を記載します。
3.
学習データと、
CountVectorizer
でも
gensim
をmodels.LsiModel
を
4.
RandomForestClassifier
でLinearSVC
とfit
を
5.
TSV
をunknown
ラベルにLinearSVC
だと、decision_function
で、
RandomForestClassifier
だと、predict_proba
で、
この0.5
よりも0.5
以下の
unknown
を
6.
結果を、
gspread
を
1行ずつupdate_cells
でまとめて
スプレッドシート
以下のような、
検索キーワードを LinearSVCで クラス分類してみた 時との 比較
以下、
1単語のみの
キーワードの 分類結果に ついて 確からしさの 単位の 違い( decision_function
とpredict_proba
の違い)と、 1単語に 対する ラベルを 割り当てた、 と いう ところが あるのかもしれませんが、 1単語に 対する 分類は、 LinearSVC
に比べるとうまく 分類できているように 見えました。 分類可能な
データに ついて
LinearSVC
を使用していた 場合に 比べて、 unknown
の割合は 減少しました。
LinearSVC
はパラメータの チューニングを していなかったと いうのが 理由かもしれないので、
パラメータのチューニングを すると、 結果が 変わるかもしれません。
LinearSVC
でのRandomForestClassifier
での
素人目線で、LinearSVC
よりも
以上です。
コメント