タイトル:オープンデータのRDF化のための項目名のクラスタを使用した述語のサジェストに関する研究
タイトル(英語):A study on suggestion of predicates using the clustering of item names for making RDF of Open Data
近年,世界的にオープンデータへの関心が高まりつつある。オープンデータの活用が推進され,オープンデータの公開,活用に取り組んでいるが,公開のデータも名前空間の共通化にほとんどなされていない。本研究では,RDFに焦点を当てて,述語の語彙共通化を行うため,オープンデータの項目名をクラスタリングし, 割り当てられたカテゴリを教師信号として,Deep Learningで学習し,述語のサジェストを提案する。また、述語の予測の結果を示す。
(200文字)
#20191217 08:41 import pandas as pd import pandas.io.common import numpy as np import codecs import random import os #import getenc import time import re import sys import keras import matplotlib.pyplot as plt from gensim.models import Word2Vec from janome.tokenizer import Tokenizer from keras.utils.np_utils import to_categorical from pandas import Series,DataFrame from sklearn.model_selection import train_test_split from keras.models import Sequential from keras.layers import Activation, Dense, Dropout from keras.utils.np_utils import to_categorical from keras.utils import np_utils from keras.utils.vis_utils import plot_model from keras.optimizers import RMSprop from keras.models import load_model from sklearn.preprocessing import LabelEncoder from progressbar import * from keras.layers import BatchNormalization from scipy.cluster.hierarchy import linkage,dendrogram,fcluster import japanize_matplotlib #import seaborn as sns #sns.set(font="IPAexGothic") #日本語フォント設定 #パラメータ設定 TRAIN_TIMES = 100 # 学習回数 NUM_DATAS = 3000 # データのデータ数(学習サンプル数) TEST_SIZE = 0.2 #テスト割合 BATCH_SIZE = 512 # 1回の学習に用いるデータ数 NUM_SEED = 0 #乱数のシード値 INPUT_DIMENSION = 50 # 入力データの次元数 HIDDEN_DIMENSION = 300 # 隠れ層の次元数 NUM_CLASSES = 2 # 出力の次元数(クラスタ数:教師信号学習ラベル用) RATIO_DROPOUT =0.5 #削除するユニットの割合(過学習を防ぐため) DEL_TIMES =20 #重複回数以下datasetを削除 HIDDEN_LAYERS = 2 #隠れ層の層数 ACTIVATION_FUNCTION='relu' #活性化関数 ACTIVATION_FUNCTION_OUTPUT='softmax'#活性化関数(出力層) WIDGETS = ['Progress of making dataset: ',Percentage(), ' ', Bar('#'),' ', Timer(),' ', ETA(), ' ', FileTransferSpeed()] FNAME="item_data_all_20191219_new.csv" F_MODEL_NAME = "word2vec.gensim.model" #モデルの作成 def create_model(): #モデルの定義(畳み込みニューラルネットワーク) model = Sequential() #入力層 model.add(Dense(HIDDEN_DIMENSION,input_dim = INPUT_DIMENSION)) model.add(Activation(ACTIVATION_FUNCTION)) #隠し層 for i in range(HIDDEN_LAYERS): model.add(Dense(HIDDEN_DIMENSION)) model.add(BatchNormalization()) model.add(Dropout(RATIO_DROPOUT)) #出力層 model.add(Dense(NUM_CLASSES))#引数は分類の数を定義する model.add(Activation(ACTIVATION_FUNCTION_OUTPUT)) model.summary()# モデル構成の確認 #ここまででモデルの層完成 #lossは損失関数を定義するところ model.compile(loss="categorical_crossentropy",metrics = ["accuracy"],optimizer = "adam")#'rmsprop' "adam" #学習モデル図の作成 plot_model(model, to_file='model.png') return model #結果をグラフにプロット関数 def plot_history(history): # 精度の履歴をプロット plt.plot(history.history['acc'],"o-",label="accuracy") plt.plot(history.history['val_acc'],"o-",label="val_acc") plt.title('model accuracy') plt.xlabel('epoch') plt.ylabel('accuracy') plt.legend(loc="lower right") #plt.show() plt.savefig('accuracy.jpg') # 損失の履歴をプロット plt.plot(history.history['loss'],"o-",label="loss",) plt.plot(history.history['val_loss'],"o-",label="val_loss") plt.title('model loss') plt.xlabel('epoch')# x方向のラベル plt.ylabel('loss') # y方向のラベル #plt.legend(loc='lower right') plt.ylim(0,5)# グラフの表示範囲(y方向) plt.legend(bbox_to_anchor=(1,1)) #plt.show() plt.savefig('loss.jpg')#グラフをファイルに保存する #日本語をベクトルに変換する関数 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) return vec #クラスタリングの処理関数 def cluster_func(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() print(df_name) f_save ="label_"+me+"_"+met+"_"+str(class_num)+"_"+"cluter.csv" print(f_save) 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__": start = time.time() # 0.データの準備(データの前処理) print("Word2Vec reading...") word2vec_model =Word2Vec.load(F_MODEL_NAME) print(word2vec_model) print(" CSV of item data reading...") df=pd.read_csv(FNAME,sep=",",header=0) #項目データ 項目名ペアを読み込み print(df) len_df=len(df) dict ={} #回数を統計 for i in range(len_df):#len(df)): if df.iat[i,1] in dict.keys(): dict[df.iat[i,1]]+=1 else: dict[df.iat[i,1]] =1 print(dict) list_drop =[ i for i in range(len_df) if dict[df.iat[i,1]] <= DEL_TIMES] df=df.drop(index=list_drop).reset_index(drop=True) df=df.head(NUM_DATAS)#指定した件数 print("\ndone") list_dataset = []#ベクトル保存用 list_name =[]#ラベルの数を計算用 pbar = ProgressBar(widgets=WIDGETS, maxval=NUM_DATAS).start()#プログレスバーのスタート for i in range(len(df)):#項目データを分かち書きし、ベクトル変換 vec=word_to_vec(df.iat[i,0])#分かち書きi行目0列目➡項目データ if(type(vec) is int):#無い場合:0 continue list_dataset.append([vec,df.iat[i,1]]) if df.iat[i,1] not in list_name: list_name.append(df.iat[i,1]) pbar.update(i)#処理の進捗状況をプログレスバーとして表示 pbar.finish()#プログレスバーの終了 process_time = format(time.time() - start) print('making dataset time is %s s'%process_time) start = time.time() label_dict=cluster_func(list_name,NUM_CLASSES,'average','cosine',True,True) print(label_dict) df_tmp = pd.DataFrame(list_dataset) print(df_tmp) item_data = df_tmp[0].values item_data = pd.DataFrame(item_data.tolist())#項目データ変更:ndarrayの配列をリストへ変換 label_list =[label_dict[df.iat[k,1]] for k in range(len(df_tmp))]#ラベル item_name=np.array(label_list) print(item_name) print(type(item_name)) le = LabelEncoder() item_name_tmp = le.fit_transform(item_name) item_name_enc = to_categorical(item_name_tmp,num_classes=NUM_CLASSES) print(item_name_enc) # 1.データセットの用意 X=item_data Y=item_name_enc (x_train, x_test, y_train, y_test) = train_test_split(X,Y, test_size=TEST_SIZE,random_state=NUM_SEED) # 2.モデルの作成・コンパイル model = create_model() # 3.モデルの学習 history = model.fit(x_train, y_train, epochs=TRAIN_TIMES, batch_size=BATCH_SIZE,validation_data=(x_test, y_test)) # 4.モデルの評価 loss,accuracy = model.evaluate(x_train,y_train,verbose=1) print("訓練\n損失率loss={} 精度accuracy={}".format(loss, accuracy)) loss,accuracy = model.evaluate(x_test,y_test,verbose=1) print("テスト\n損失率loss={} 精度accuracy={}".format(loss, accuracy)) plot_history(history) print("done") process_time = format(time.time() - start) print('Learning time is %s s'%process_time)
LabelEncoderはラベルを0~クラスの種類数n-1の値に変換する。