Google Search Console の
学習データに
[1].やはり
前提
入力データ 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 |
クラス分類の 手順
以下の
クラスタリングには、sklearn
のLinearSVC
を
Google スプレッドシートの
学習データを TSV
にして 読み込み、 キーワードを 抽出。 サーチコンソールからの
取得結果の Google スプレッドシートを CSV
にして 読み込み、 キーワードを 抽出。 学習データと、
サーチコンソールからの 取得結果の キーワードを マージ、 キーワード内の 単語の 出現頻度を 数えて、 結果を 素性ベクトル化する。
2
[2]キーワードをマージは、 サーチコンソールからの 取得結果の キーワードは 時間が 経つと 変わっていく (増えていく )ため、
素性ベクトル作成時に、次元数を 揃える ?ために 実施しています。 (実際いらないのかもしれませんが たぶん 必要) LinearSVC
で学習 CSV
をクラス分類して、 スコアを 取得、 確からしさが 低い データに ついては、 分類結果の ラベルは 付与せず、 unknown
ラベルに置換 結果を
CSVに 書き出し、 Google スプレッドシートに インポートし、 グラフ表示
各種ライブラリの インストール
必要な
pip install sklearn numpy scipy pandas
以下の
pip list | grep -e sklearn -e numpy -e scipy -e pandas --------------------------- numpy (1.12.1) pandas (0.20.1) scipy (0.19.0) sklearn (0.0) ---------------------------
実装
以下、
search_console_svm_classsifier.py
以下、
3.6. scikit-learn: Python での
search_console_svm_classsifier.py
# -*- coding: utf-8 - from __future__ import print_function import sys import numpy as np import pandas as pd from sets import Set from sklearn import svm from sklearn.feature_extraction.text import CountVectorizer stop_words = Set(['name', 'not', 'the', 'usr', 'you', 'version', 'this']) # 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(" ") after_text = " ".join([keyword for keyword in keywords if check_stop_word(keyword)]) return after_text # report csv を parse する def parse_report_csv(): lines = [] row_count = 1 for line in open('Google_Search_Console.csv', 'r'): if row_count != 1: arr = line.split(",") # キーワードカラムを取り出す lines.append(arr[1]) row_count += 1 return lines # learning_tsv parseする def read_from_learning_tsv(index): lines = [] row_count = 1 for line in open('LearningData.tsv', 'r'): if row_count != 1: arr = line.split("\t") # キーワードカラムを取り出す lines.append(arr[index]) row_count += 1 return lines def get_min_abs_dict(array, score): # 最小絶対値として、設定されない値であろう[sys.maxint] を設定 min_abs = sys.maxint index = 0 for i in range(len(array)): item = abs(array[i]) if min_abs > item: min_abs = item index = i return {score[index]: min_abs} # メインメソッド def execute(): # ---------------------------------------------------------------------------- # 3. 学習データと、サーチコンソールからの取得結果のキーワードをマージ、キーワード内の単語の出現頻度を数えて、結果を素性ベクトル化する。 # ------------------------------------------------------ keywords = [] # 学習データからキーワードを取得 for line in read_from_learning_tsv(0): keywords.append(split_keyword(line)) # CSVからキーワードを取得 for line in parse_report_csv(): keywords.append(split_keyword(line)) # テキスト内の単語の出現頻度を数えて、結果を素性ベクトル化する(Bag of words) count_vectorizer = CountVectorizer() # csr_matrix(疎行列)が返る feature_vectors = count_vectorizer.fit_transform(keywords) print("word数:" + str(len(feature_vectors.toarray()[0]))) # 学習したデータのみ切り出し learning_vectors = feature_vectors[:len(read_from_learning_tsv(0))] # データに対応したラベルを取得 learning_labels = np.array(read_from_learning_tsv(1)) # ------------------------------------- # 4. `LinearSVC` で学習 # -------------------------------- # SVCのロード clf = svm.LinearSVC() # 学習 clf.fit(learning_vectors, learning_labels) # -------------------------------------- # 5. `CSV` をクラス分類して、スコアを取得、確からしさが低いデータについては、分類結果のラベルは付与せず、`unknown` ラベルに置換 # -------------------------------------- scores = clf.decision_function(feature_vectors[len(read_from_learning_tsv(0)):]) classes = clf.classes_ labels = [] for score in scores: min_abs_dict = get_min_abs_dict(score, classes) for k, v in min_abs_dict.items(): if 0.90 >= v: # 0.90 以下は、ラベルを設定 labels.append(k) else: # 0.90 より大きい場合は "unknown" labels.append("unknown") # CSVを再度読み込み、ラベル名を追加して、CSV書き出し output_df = pd.read_csv('Google_Search_Console.csv') output_df['label_name'] = labels output_df.to_csv('Google_Search_Console_Output.csv', encoding="utf-8", index=False) if __name__ == '__main__': execute()
説明
以下、説明を 記載します。
1.
Google スプレッドシートのTSV
に
TSV
に
Google_Search_Console.csv
に
現在(2017/05/21)だと、
3.
学習データと、
最初mecab
で
短すぎる
split_keyword
メソッド内で、
素性ベクトル作成後、
learning_vectors = feature_vectors[:len(read_from_learning_tsv(0))]
で、TSV
データの
4.
LinearSVC
でLinearSVC
をSVC
で
パラメータ指定なしの
もっと
5.
CSV
をunknown
ラベルに
decision_function
で、
こいつは、
get_min_abs_dict
と
0.9
以下だったら、unknown
と
0.9
は、
ちなみに、LinearSVC
で、predict_proba
を
AttributeError: 'LinearSVC' object has no attribute 'predict_proba'
6.
結果を
一旦
以下のような、
[3].unknown
の
検索キーワードを LinearSVCで クラス分類してみた 感想
以下、
- 1単語のみの
キーワードが うまく 分類できていない。
3word 以上の分類は、 結構うまく いっているように 見えましたが、
例えばSonarQube 日本語
がうまく 分類できず、 unknown
になります。
これは、IntelliJ 日本語
をIntelliJ
とする 学習データが あったりするのが、
影響にしているのだろうと 思ったりします。
「カテゴリを 示す キーワード」の 重みづけを する。 or 「学習データ」を 調整するなどが 必要に 思いました。
- 形態素解析は
不要?
形態素解析後のwordで 学習、 クラス分類しても いい 感じには ならなかったです。
検索エンジンに対して、 送りつける ワードは 基本スペース区切りなので、
「なんらかの 意味を もつWORDが スペース区切りで 入力されている」 前提で、 分析した ほうが いい 結果がでるのかもしれません。
ここは、KMeans
でクラスタリングしてた 時と 同じでした。
クラス分類の
[4].今の
以上です。
コメント