Google Search Console の
正直、
カテゴリ分けの
[1].実務に
動機
以前、
Search Analytics for Sheets - Google スプレッドシート アドオン で、
データを Export 1.
でバックアップした 月別シートを マージ 2.
でマージした シートを、 Google データスタジオ で、 グラフ表示。
すると
これでざっくり
クラスタリングの 手順
以下の
クラスタリングには、sklearn
のKMeans
を
クラスタ数の 決定
クラスタ数の
実装は、
Google スプレッドシートを
CSV
にして 読み込み、 キーワードを 抽出。 キーワード内の
単語の 出現頻度を 数えて、 結果を 素性ベクトル化する。 エルボー法で、
最適な クラスタ数を 決定する。
クラスタリング
Google スプレッドシートを
CSV
にして 読み込み、 キーワードを 抽出。 キーワード内の
単語の 出現頻度を 数えて、 結果を 素性ベクトル化する。 sklearn
のKMeans
でクラスタリング 各クラスターで
もっとも 頻出する 単語を クラスターの ラベル名と して 設定、 結果を CSVに 書き出す。 Google スプレッドシートに
インポートし、 グラフ表示
各種ライブラリの インストール
必要な
[2].以下で
pip install sklearn numpy scipy pandas matplotlib
実装
以下、
クラスタ数の<wbr>決定
と、クラスタリング
を
クラスタ数の 決定 (plot_elbow.py)
以下、
scikit-learnを
k-meansの
2つを
- plot_elbow.py
# -*- coding: utf-8 - from __future__ import print_function import matplotlib.pyplot as plt import numpy as np import pandas as pd from __builtin__ import xrange from sets import Set from sklearn.cluster import KMeans 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 # メインメソッド def execute(): keywords = [] 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) # エルボー法 distortions = [] # クラスタ数は100 n_clusters = 100 for i in range(1, n_clusters): km = KMeans(n_clusters=i, init='k-means++', # k-means++法によりクラスタ中心を選択 n_init=10, max_iter=300, random_state=0) km.fit(feature_vectors) # クラスタリングの計算を実行 distortions.append(km.inertia_) # km.fitするとkm.inertia_が得られる plt.plot(range(1, n_clusters), distortions, marker='o') plt.xlabel('Number of clusters') plt.ylabel('Distortion') plt.show() if __name__ == '__main__': execute()
説明
以下、
1.
Google スプレッドシートをCSV
に して 読み込み、 キーワードを 抽出。
csv を
2.
キーワード内の 単語の 出現頻度を 数えて、 結果を 素性ベクトル化する。
最初mecab
で
短すぎる
3.
エルボー法で、 最適な クラスタ数を 決定する。
クラスタ数100までで
データ量は、
エルボ〜図
以下、
25-26 あたりが
クラスタリング (search_console_classsifier.py)
KMeans
でpython
プログラムです。
- search_console_classsifier.py
# -*- coding: utf-8 - from __future__ import print_function import pandas as pd from __builtin__ import xrange from sets import Set from sklearn.cluster import KMeans 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 # メインメソッド def execute(): # CSVからキーワードを取得 keywords = [] 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]))) # テキスト内の単語の出現頻度を数えて、結果を素性ベクトル化する(Bag of words) count_vectorizer = CountVectorizer() # csr_matrix(疎行列)が返る feature_vectors = count_vectorizer.fit_transform(keywords) # 単語の一覧を取得 vocabulary = count_vectorizer.get_feature_names() # クラスタ数は[25] n_clusters = 25 km = KMeans(n_clusters=n_clusters, init='k-means++', # k-means++法によりクラスタ中心を選択 n_init=10, max_iter=300, random_state=0) # データフレーム作成 df = pd.DataFrame(feature_vectors.toarray()) pred = km.fit_predict(df) # クラスタリング結果をデータフレームに設定 df['cluster_id'] = pred # ------------------------------------ # ラベルとラベル名称の辞書の紐付け # ------------------ label_name_dict = {} # クラスタ数分繰り返し for i in xrange(n_clusters): # クラスタIDでデータを抽出して平均値をとる series = df[df['cluster_id'] == i].mean() # cluster_id を削除しておく series = series.drop(['cluster_id']) label_name = "" # 値を降順ソート(大きい順)で並べ替え、[1]番大きいデータを取得 for index, value in series.sort_values(ascending=False)[:1].iteritems(): if value > 0: # 一番大きい(1番登場した単語)をラベル名にする label_name += vocabulary[index] label_name_dict.update({i: label_name}) # CSV出力のため、ラベルIDをラベル名に変換 label_names = [] for elem in pred: label_names.append(label_name_dict.get(elem)) # CSVを再度読み込み、ラベル名を追加して、CSV書き出し output_df = pd.read_csv('Google_Search_Console.csv') output_df['label_name'] = label_names output_df.to_csv('Google_Search_Console_Output.csv', encoding="utf-8") if __name__ == '__main__': execute()
説明
以下、
3.
sklearn
の KMeans
で クラスタリング
k-meansの
を
4.
各クラスターで もっとも 頻出する 単語を クラスターの ラベル名と して 設定、 結果を CSVに 書き出す。
pandas
で
5.
Google スプレッドシートに インポートし、 グラフ表示
一旦CSVで
以下のような、
検索キーワードを クラスタリングしてみた 感想
以下、
- 形態素解析は
不要?
形態素解析後のwordで クラスタリングしても いい 感じには ならなかったです。
検索エンジンに対して、 送りつける ワードは 基本スペース区切りなので、
「なんらかの 意味を もつWORDが スペース区切りで 入力されている」 前提で、 分析した ほうが いい 結果がでるのかもしれません。
- 代表語が
いい 感じなのに、 分類結果を 見ると[その 他]っぽい ものが ある。
円グラフ上のbrew
がそうなのですが、 キーワードに brew
がなかったりします。
このラベルだけ、 ごった 煮感が 出ていて、 詳細に カテゴリ分けした ほうが よさそうに 思いました。
- いい
感じに 代表的な 言葉が ついて、 分類できている ことろも ある。
感覚ベースだと、5-6割は いい 感じになっているように 思います。
最もClick数が 大きい 集合 brew
がいい 感じにならなかったのが 問題ですが。。
検索キーワードの 分類と して、 素人と してどうするのが よいか?
- 案1. 基本
「教師あり」で 分類して、 分類できなかった ものを 「教師なし」
「その 他分類」の 出来加減が 非常に ストレスが 貯まる 結果でした。
キーワードに対する 分類データを 作成して、 「教師あり」であてたらよりいい 感じになるのかと 思いました。
次回やるとしたらこれかなと、で、 あまりあてにならなそうな ところを、 今回実施した 方法で 分類するとかしたら、
いい感じになりそうに 思いました。
- 案2. 代表後だけ
手動で 分類ロジックを 組んで おき、 分類できなかった ものを 「教師なし」
代表語のリストで 分類して、 分類できなかった ものを、 「教師なし」で 分類。
現状だと、そんなに キーワード数も 多くないので、 案1より、 時間が かからなそうな 気は します。
実装していて楽しくなさそうなのが デメリット。
- 案3 . マーケットバスケット分析に
よる 検索キーワードの グルーピングと 視覚化 - 廿TT等を 参考に、 現在の やりかたとは、 WORDの 解析の 仕方(思考)を 変えてみる。
キーワードだと、文章とは 違うから このようなやり方の ほうが いい 感じになるのかもしれません。
brew
でまとまったキーワードは プログラム言語違いの 横断的関心事(例えば、 セキュリティ)とか、
が含まれていた ため 名詞ベースではしっくりこない キーワードが まと まった 感は ありました。
案3
で実装する とこの ケースが いい 感じに 分類(または 視覚化)されそうに 思いました。
今回作った
以上です。
コメント