#author("2020-09-04T04:16:27+00:00","default:f-lab","f-lab")
[[個人ページ>seminar-personal/chin2017]]
&br;
[[N班ゼミ>http://f-lab.mydns.jp/index.php?seminar-N-2020]]
|~目次|
|#contents|
&br;
*閾値法による結果と階層クラスタリングの結果の比較 [#vc59b533]
**実装 [#ed8e61de]
***閾値法 [#dea1acbc]
-閾値を使う方法の手順
--①類似度の閾値shを適当に決める
--②すべての項目名について、他の項目名との類似度を計算し、sh以上のものをクラスタ候補とする。
--③すべての項目名のクラスタの中心を計算(各グループの中心を求める)。->グループに所属する各点の平均を求めて、グループの中心にしています
--④重複している項目名と所属しているクラスタの中心の類似度が高いほうのみを残る
-ソースコード
 #%% imports
 import pyclustering
 from scipy.cluster.hierarchy import linkage,dendrogram,fcluster
 import numpy as np
 import pylab
 from gensim.models import Word2Vec
 import pandas as pd
 import pandas.io.common
 import numpy as np
 import codecs
 import random
 import os
 import time
 import re
 import sys
 from janome.tokenizer import Tokenizer
 SH=0.6#類似度の閾値sh
 F_MODEL_NAME ="../model/gs_cbow_50.model"
 FNAME="datasets_4times_item_names_654.csv"
 NORMAL_FLG=1#正規化
 FNAME_SAVE="3times_normal_50_"+str(SH)+".csv"
 print("Word2Vec reading...")
 word2vec_model =Word2Vec.load(F_MODEL_NAME)
 #日本語をベクトルに変換する関数
 def word_to_vec(item):
     t = Tokenizer()#分かち書き
     items =[token.surface for token in t.tokenize(item)]
     vec =sum(word2vec_model[items[l]] for l in range(len(items)) if items[l] in word2vec_model.wv)
     #print(type(vec))
     return vec
 #ベクトルの正規化
 def normalization(x):
     y=np.array(x)
     d=np.linalg.norm(y)
     x_norm = y/d
     return x_norm
 #ベクトルの類似度を計算
 def cos_similarity(v1, v2):
     return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
 #ラベル番号を付け
 def clustering_to_clusters(list_clusters,dict_n):
     names_list=[]
     for k in range(len(list_clusters)):
         for j in range(len(list_clusters[k])):
             line =[]
             line.append(list_clusters[k][j])
             #print(type(dict_n[list_clusters[k][j]]))
             for l in range(len(dict_n[list_clusters[k][j]].tolist())):
                  line.append(dict_n[list_clusters[k][j]][l])
             line.append(k)
             names_list.append(line)
     df = pd.DataFrame(names_list)
     #print(df)
     return df
 #クラスタの重なり率を計算
 def overlap_rate(cluster_list):
     rate_list=[]
     for i in  range(len(cluster_list)): 
         rates_names = []
         for j in range(len(cluster_list)):
             if cluster_list[i]==cluster_list[j]:
                 rates_names.append(1)
             else:
                 m=0
                 for k in range(len(cluster_list[i])):
                     if cluster_list[i][k] in cluster_list[j]:
                         m=m+1
                 rates_names.append((2*m)/(len(cluster_list[i])+len(cluster_list[j])))
         rate_list.append(rates_names)
     df = pd.DataFrame(rate_list)
     #print(df)
     return df
 #各グループの中心を求める
 def cluster_average(group_list,dict_n):
     if len(group_list) ==1:
         return dict_n[group_list[0]]
     else:
         vec =sum(dict_n[group_list[l]] for l in range(len(group_list)))
         average_vec=vec/len(group_list)
         return average_vec
 #全クラスタに最大の類似度を計算し、記録(削除用関数)
 dic_max={}
 def max_cosine_all(word_list,cluster_list_all,dict_n):
     for k in range(len(word_list)):
         cosine_value =0        
         for i in range(len(cluster_list_all)):            
             if word_list[k] in cluster_list_all[i]:
                 word= word_list[k]
                 if len(cluster_list_all[i]) ==1 and word_list[k] == cluster_list_all[i][0]:
                     cosine_value =1#同じ単語
                 else:
                     tmp =cos_similarity(dict_n[word], cluster_average(cluster_list_all[i],dict_n))
                     if tmp > cosine_value:
                         cosine_value = tmp
         dic_max[word_list[k]]=cosine_value
         #print(dic_max[word_list[k]])
 #クラスタの要素を削除
 def del_cluster(cluster_list,dict_n):
     new_list =[]
     for i in range(len(cluster_list)):
         tmp=[]
         words_list= cluster_list[i]
         if len(words_list) ==1:
             tmp.append(cluster_list[i][0])
         else:
             for k in range(len(cluster_list[i])):
                 word = cluster_list[i][k]
                 cos=cos_similarity(dict_n[word],  cluster_average(words_list,dict_n))
                 if cos !=1 and cos ==dic_max[word]:
                     tmp.append(cluster_list[i][k])
         if len(tmp)>0:
             new_list.append(tmp)
     return new_list
 #SH閾値法によるクラスタリング関数
 def sh_clustering(list_name):
     dict_n ={}
     df_vec=[]
     df_name =[]
     for i in range(len(list_name)):#len(list_name)
         tmp=[]
         if type(word_to_vec(list_name[i])) is not int:
             if NORMAL_FLG == 1:
                 vec =normalization(word_to_vec(list_name[i]))#.tolist()#正規化
             else:
                 vec = np.array(word_to_vec(list_name[i]))#.tolist()#正規化しない
             df_vec.append(vec)
             df_name.append(list_name[i])
             dict_n[list_name[i]]=vec
     clusters_words=[]
     k=0
     for i in range(len(df_name)):
         words=[df_name[i]]
         for j in range(len(df_name)):
             if df_name[i] == df_name[j]:
                 continue
             if cos_similarity(dict_n[df_name[i]], dict_n[df_name[j]]) >= SH:
                 words.append(df_name[j])
         clusters_words.append(sorted(words))
         k+=1
     clusters_words = list(map(list, set(map(tuple, clusters_words))))#重複の要素を除外
     clusters_other = []
     clusters_list =[]
     for m in range(len(clusters_words)):
         if len(clusters_words[m]) >1:
             clusters_list.append(clusters_words[m])
         else:
             clusters_other.append(clusters_words[m])
     df_rate =overlap_rate(clusters_words)
     df_rate.to_csv("overlap_rate_100_"+str(SH)+".csv",index=True,encoding="utf-8-sig")
     # 重複を削除
     df_cluster= clustering_to_clusters(clusters_words,dict_n)
     df_cluster.to_csv(FNAME_SAVE,index=False,encoding="utf-8-sig",header = False)
     max_cosine_all(df_name,clusters_words,dict_n)
     new_list =del_cluster(clusters_words,dict_n)
     print(len(new_list))
     # クラスタを取得できる
     df_cluster= clustering_to_clusters(new_list,dict_n)
     FNAME_SAVE2="3times_normal_50_"+str(SH)+"_2"+ +str(len(new_list)))+".csv"
     df_cluster.to_csv(FNAME_SAVE2,index=False,encoding="utf-8-sig",header = False)
     return new_list
 #階層型クラスタリングの処理関数
 def hierarchical_clustering(arr,class_num,me,met,view_flg,csv_flg):
     dict_label ={}
     df_vec =[np.array(word_to_vec(l)).tolist() for l in arr if type(word_to_vec(l)) is not int]
     df_vec = pd.DataFrame(df_vec)
     # 階層型クラスタリングの実施
     # 平均法 x cosine距離
     result = linkage(df_vec,method=me,metric =met)
     # クラスタリング結果の値を取得
     clusters = fcluster(result, t=class_num,criterion='maxclust')
     clusters_list= clusters.tolist()
     # 階層型クラスタリングの可視化
     if (view_flg ==True):
         plt.figure(num=None, figsize=(16, 9), dpi=200, facecolor='w', edgecolor='k')
         #デンドログラムを表示
         dendrogram(result,labels=item_name_labels)
         plt.show()
     if(csv_flg ==True):
         df_name=[[l]+np.array(word_to_vec(l)).tolist() for l in arr if type(word_to_vec(l)) is not int]
         df_name = pd.DataFrame(df_name)
         df_name['cluster'] = clusters.tolist()
         f_save ="label_"+me+"_"+met+"_"+str(class_num)+"_"+"cluter.csv"
         df_name.to_csv(f_save,index=False,header=False)
     #for m in range(len(arr)):
     #    name =arr[m]
     #    cluster =clusters_list[m]
     #    dict_label[name] = cluster
     #return dict_label 
 if __name__ == "__main__":
     print(" CSV of item data reading...")
     df=pd.read_csv(FNAME,sep=",",header=None) #読み込み
     list_name =[]#ラベルの数を計算用
     for i in range(len(df)):
         list_name.append(df.iat[i,0])
     print(len(list_name))
     NUM_CLASSES =len(sh_clustering(list_name))
     hierarchical_clustering(list_name,NUM_CLASSES,'average','cosine',False,True)

**結果 [#ia50e762]
*階層クラスタリングによる同クラスラスを設定し、クラスタの結果を比較 [#jf3479b0]
|生データ|閾値法の分布図|階層的クラスタリングの分布図|
|3自治体以上項目名(654個)|&ref(sh_0.6_489.png);||
|4自治体以上項目名(1184個)|&ref(sh_0.6_857.png);||
|100個単語|||



トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS