두 가지 특징적인 분산 표현을 측정

용도



특정 문장군에 대해 문장분류를 할 때 SVM(SupportVectorMachine)+FeatureSelection을 사용하면 단순히 분류가 가능할 뿐만 아니라 그 분류에 기여하는 소성을 순위화할 수 있다. (그러므로, 노이즈가 없는 상태에서 실험할 수 있으므로 정밀도가 오른다.차원 압축에도 도움이 된다)
이 특성이 분산 표현으로 어떻게 표현되는지 조사하는 것이이 프로그램.

사용할 데이터



*SVM+FS로 추출된 텍스트 파일
*word2vec로 작성한 일본어 Wikipedia 전 기사의 모델

SVM+FS.txt
# 3.22/w.o
  1  0.2144     142     146 1:株式会社           -0.2309       9      21 1:レストランチェーン
  2  0.1981     108     119 1:を                     -0.1946       0       3 1:Tughril                
  3  0.1959     503     588 1:経営                  -0.1763      64     382 1:(\"                  
  4  0.1821      33      34 2:、                     -0.1759      70      86 1:)",                  
  5  0.1743     407     488 1:企業                  -0.1737       1      15 1:Grill                     

이번에 준비한 데이터는 SVM에서 출력되는 오리지널이 아니라 거기에서 작성한 것입니다. 생략하고 top5만 올리고 있습니다.

프로그램



ALL.py
# -*- coding:utf-8 -*-
from janome.tokenizer import Tokenizer
from gensim.models import word2vec
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from matplotlib import rcParams
from matplotlib.backends.backend_pdf import PdfPages
import glob
import torch.nn.functional as F
import torch
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster

t = Tokenizer()
plt.rcParams["font.size"] = 18
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP']

model = word2vec.Word2Vec.load("./wiki_model.sg1")

reject = [')",','(','),','、','。',"'",',(',', ','・','。",','\\")','(\\"','\n']

def words_append(wordsp,wordsn):
    with open("./SVM+FS.txt") as fs:
        fslist0 = fs.readlines()
        fslist = []
        for m in fslist0:
            m = m.replace("\n","")
            fslist.append(m)
        del fslist0
        positive = []
        negative = []
        for m in fslist:
            line = m.split(" ")
            line2 = [a for a in line if a != '']
            try:
                positive.append(line2[4])
                negative.append(line2[8])
            except:
                pass
        del line,line2
        for i,m in enumerate(positive):
            mm = m.split(":")
            if not mm[1] in reject:
                mm[1] = mm[1].replace("\n","")
                tokens = t.tokenize(mm[1])
                for token in tokens:
                    # 品詞を取り出し
                    partOfSpeech = token.part_of_speech.split(',')[0]
                    if partOfSpeech == "名詞":
                        wordsp.append([mm[1],"r"])
                        break
        for i,m in enumerate(negative):
            mm = m.split(":")
            if not mm[1] in reject:
                mm[1] = mm[1].replace("\n","")
                tokens = t.tokenize(mm[1])
                for token in tokens:
                    # 品詞を取り出し
                    partOfSpeech = token.part_of_speech.split(',')[0]
                    if partOfSpeech == "名詞":
                        wordsn.append([mm[1],"b"])
                        break

def plotM(wordsp,wordsn):
    labels = []
    print(len(wordsp),len(wordsn))
    length = len(wordsp)
    datap = []

    j = 0
    while j <= length:
        try:
            datap.append(model[wordsp[j][0]])

        except:
            try:
                print(wordsp[j])
                del wordsp[j]
            except:
                pass
        j += 1
    # print(f'{"datap is"} {datap}')
    length = len(wordsn)
    datan = []

    j = 0
    while j <= length:
        try:
            datan.append(model[wordsn[j][0]])

        except:
            try:
                del wordsn[j]
            except:
                pass
        j += 1

    if len(wordsp) > len(wordsn):
        print("TypeA")
        for i in range((len(wordsp) - len(wordsn))):
            wordsp.pop()
    elif len(wordsn) > len(wordsp):
        print("TypeB")
        for i in range((len(wordsn) - len(wordsp))):
            wordsn.pop()

    print(len(wordsp),len(wordsn))
    length = len(wordsp)
    datap = []

    j = 0
    while j <= length:
        try:
            datap.append(model[wordsp[j][0]])
            x = wordsp[j][0]
            x = x + "+"
            labels.append(x)
        except:
            pass
        j += 1
    # print(f'{"datap is"} {datap}')
    length = len(wordsn)
    datan = []

    j = 0
    while j <= length:
        try:
            datan.append(model[wordsn[j][0]])
            x = wordsn[j][0]
            x = x + "-"
            labels.append(x)
        except:
            pass
        j += 1

    pca = PCA(n_components=2)
    pca.fit(datap)
    pca.fit(datan)
    data_pcap= pca.transform(datap)
    data_pcan= pca.transform(datan)

    pdata = torch.from_numpy(data_pcap)
    ndata = torch.from_numpy(data_pcan)
    out = F.kl_div(pdata, ndata)  
    print(out)


    #----
    A = data_pcap
    B = data_pcan
    AB = len(A)+len(B)
    #print(A)
    #data = A + B
    #print(len(data))
    print(len(labels))
    data = np.zeros(shape=(AB,2))
    count = 0
    for i,m in enumerate(A):
        data[i] = m
        count+=1
    for i,m in enumerate(B,start = count):
        #print(i)
        data[i] = m
    #print(data)
    print(f'{len(A)},{len(B)},{len(data)}')

    # 階層型クラスタリングの実施
    # ウォード法 x ユークリッド距離
    linkage_result = linkage(data, method='ward', metric='euclidean')

    # クラスタ分けするしきい値を決める
    threshold = 0.7 * np.max(linkage_result[:, 2])

    # 階層型クラスタリングの可視化
    plt.figure(num=None, figsize=(16, 9), dpi=200, facecolor='w', edgecolor='k')
    dendrogram(linkage_result, labels=labels, color_threshold=threshold)
    #dendrogram(linkage_result, labels=labels)
    plt.show()

    # クラスタリング結果の値を取得
    clustered = fcluster(linkage_result, threshold, criterion='distance')

    # クラスタリング結果を比較
    print(clustered)

    #------

    # length_data = len(data_pca)

#     i = 0
#     while i < length_data:
#         #点プロット
#         plt.plot(data_pca[i][0], data_pca[i][1], ms=5.0, zorder=2, marker="x", color=words[i][1])

#         #文字プロット
#         plt.annotate(words[i][0], (data_pca[i][0], data_pca[i][1]), size=7)

#         i += 1
#         title = "r料理店とb茶店"
#         plt.title(title, fontsize=18)
#     plt.savefig("./"+str(title)+".png")
#     # plt.show()

words = []
wordsp = []
wordsn = []
words_append(wordsp,wordsn)
plotM(wordsp,wordsn)


덧붙여 덧붙여서 만든 프로그램으로, 게다가 센스 없기 때문에 쓰레기 프로그램이라고 말해질지도 모릅니다만, 참고가 되면 기쁩니다.

KL-div는 PyTorch로 계산됩니다.
계층 적 클러스터링은 scipy에서 수행됩니다.

결과를 조금



요리점과 찻집이라는 동의어(분류 어휘표에서는)를 이용해 그 단어를 포함한 기사를 Wikipedia에서 추출, SVM+FS를 행한 결과 FS:200에서 분류 정밀도가 최고가 되었다. 그래도 분류 정밀도는 0.664.

거기서 추출한 FS정부 top100단어의 명사만의 분산 표현을 wikipedia 전체 기사로부터 작성한 모델로부터 추출. PCA로 2 차원까지 떨어 뜨려 산포도를 작성한다. (여기는 프로그램에서 코멘트 아웃되었습니다)


적색과 청색의 분산 표현군은 가까운 곳에서 살포되어 있기 때문에 KL-div도 0.0019이다.
그러나. 두 그룹이 서로 섞여 하나의 클러스터를 형성하는 부분도 있습니다 (오른쪽 끝).
이것을 추출하는 것은 계층 적 클러스터링입니다.


이것을 보면 각 클러스터를 추출 할 수 있습니다.

죄송합니다, 역시 이 기사 보고 아는 사람은 변태라고 생각합니다.
설명의 구달리 상태가 위험하다. 소중한 시간을 사용하여 읽어 주신 분, 감사합니다.

코멘트가 있으면 기다리고 있습니다.

참고문헌

좋은 웹페이지 즐겨찾기