[PYTHON] Unüberwachte Textklassifizierung mit Doc2Vec und k-means

Als die Textklassifizierung unter Verwendung von Daten durchgeführt wurde, die von Menschen als Lehrerdaten klassifiziert wurden, kamen die schädlichen Auswirkungen menschlicher Eingriffe zwischen den Daten heraus, sodass ich einen Textklassifizierer ohne Lehrer erstellte.

Probleme durch menschliche Kennzeichnung

Referenzmaterial

Was ich getan habe

Ich bedauere, dass es besser war, nach einem Graph-Algorithmus anstatt nach k-means zu klassifizieren. Der Grund dafür ist, dass es nur eine begrenzte Anzahl von Dokumenten gibt, die bei der Berechnung mit Doc2Vec Ähnlichkeit ausgeben. Mit k-means müssen Sie einmal eine Sparse-Matrix erstellen, aber wenn Sie mit einem Graph-Algorithmus klassifizieren, müssen Sie sich nicht die Mühe machen, Speicher zu verschwenden. ..

Vorteile der Erstellung von Funktionen mit Doc2Vec

Referenzcode

Es tut mir leid, dass die Kommentare mit Japanisch und Englisch gemischt sind und der Code ziemlich schmutzig ist. ..

# coding: utf-8

from gensim import corpora, models
import numpy as np
from numpy import random
random.seed(555)
from scipy.cluster.vq import vq, kmeans, whiten
from sklearn.decomposition import TruncatedSVD
from collections import defaultdict
from separatewords import MecabTokenize  #Bitte rufen Sie einen morphologischen Analysator an, der Ihrem Zweck entspricht.


class MyTexts:
    def __init__(self, text_list):
        self.text_list = text_list

    def __iter__(self):
        for line in self.text_list:
            if line==b'Nicht beigetreten': continue
            yield MecabTokenize.tokenize( line.rstrip().decode('utf-8') )


class LabeledLineSentence(object):
    def __init__(self, texts_words):
        self.texts_words = texts_words

    def __iter__(self):
        for uid, words in enumerate(self.texts_words):
            yield models.doc2vec.LabeledSentence(words, labels=['SENT_%s' % uid])


#Stellen Sie die Ähnlichkeit jedes von Doc2Vec erfassten Satzes mit der Matrix ein
#Holen Sie sich außerdem das repräsentative Wort jedes Satzes
def create_sim_vec(model,n_sent):
    base_name = 'SENT_'
    sim_matrix = []
    sim_matrix_apd = sim_matrix.append
    word_matrix = []
    word_matrix_apd = word_matrix.append
    for i_sent in xrange(n_sent):
        sim_vec = np.zeros(n_sent)
        word_list = []
        word_list_apd = word_list.append
        #Da gesendet möglicherweise nicht vorhanden ist, schließen Sie die Ausnahmebehandlung ein
        try:
            for word, sim_val in model.most_similar(base_name+str(i_sent)):
                if 'SENT_' in word:
                    _, s_idx = word.split('_')
                    sim_vec[int(s_idx)] = sim_val
                else:
                    word_list_apd(word)
        except:
            pass
        sim_matrix_apd(sim_vec)
        word_matrix_apd(word_list)
    return sim_matrix, word_matrix

#Organisieren Sie ähnliche Dokumente mit kmeans
def sent_integrate(sim_matrix,n_class):
    #Gleichmäßige Verteilung für jede Dimension
    whiten(sim_matrix)

    centroid, destortion = kmeans(sim_matrix, n_class, iter=100, thresh=1e-05)
    labels, dist = vq(sim_matrix, centroid)
    return labels

def count_class(labels):
    res_dic = defaultdict(int)
    for label in labels:
        res_dic[label] += 1
    return res_dic

def count_labeled_data(label_data, labels):
    result_dict = {}
    for orig_labels, label in zip(label_data, labels):
        labels = np.array(orig_labels.split(), dtype=np.int64)
        if label not in result_dict:
            result_dict[label] = labels
        else:
            result_dict[label] += labels
    return result_dict


if __name__=='__main__':
    ifname = './out_data.csv'
    model_basename = './D2V/doc2vec_result/model'
    topic_result_basename = './D2V/doc2vec_result/topic'

    comment_data = []
    comment_data_apd = comment_data.append
    label_data = []
    label_data_apd = label_data.append
    with open(ifname, 'r') as f:
        for line in f:
            single_flag, label_flags, comment = line.strip().split('\t')
            comment_data_apd(comment.strip())
            label_data_apd(label_flags.strip())

    texts = MyTexts(comment_data)
    sentences = LabeledLineSentence(texts)
    model = models.Doc2Vec(alpha=0.025, min_alpha=0.025)  # use fixed learning rate
    model.build_vocab(sentences)

    # store the model to mmap-able files
    model.save(model_basename+'.d2v')

    # load the model back
    model_loaded = models.Doc2Vec.load(model_basename+'.d2v')

    epoch = 10
    for _ in xrange(epoch):
        model.train(sentences)
        model.alpha -= 0.002  # decrease the learning rate
        model.min_alpha = model.alpha  # fix the learning rate, no decay
    print 'done training'

    # show topic
    n_sent = len(comment_data)
    sent_matrix, word_matrix = create_sim_vec(model, n_sent)
    print 'done get sent_matrix'

    ##Stellen Sie ähnliche Dokumente zusammen
    #Datenkomprimierung durch svd(Dichte Daten)
    np.savetxt('./D2V/sent_matrix', np.array(sent_matrix))
    dimension = 100
    lsa = TruncatedSVD(dimension)
    info_matrix = lsa.fit_transform(sent_matrix)
    np.savetxt('./D2V/info_matrix', np.array(info_matrix))

    #Implementierung von kmeans
    n_class = 7
    labels = sent_integrate(np.array(info_matrix),n_class)
    np.savetxt('./D2V/sent_labels.csv', labels,delimiter=',', fmt='%d')
    print count_class(labels)

    #Vergleich mit dem, was Menschen klassifiziert haben
    print count_labeled_data(label_data, labels)

Die verwendeten Daten sind eine Zeile bestehend aus (0 \ t1 0 1 0 0 0 0 \ txxxx). Vom Menschen gekennzeichnete Etiketten sind mit 7 01 durch Leerzeichen getrennten Flaggen gekennzeichnet.

Kommentar

Es ist nicht glaubwürdig, da die Ergebnisse der experimentellen Daten nicht beigefügt sind. Durch visuelle Überprüfung von 2000 Daten wurden etwa 80% ohne Beschwerden klassifiziert. Im Gegenteil, als ich mir die von Menschen angebrachten Etiketten ansah, gab es ungefähr 30% von ihnen, die keinen Sinn machten. (Was ist der Unterschied in der Sensibilität ...)

Kürzlich habe ich einen Artikel veröffentlicht, ohne die Methode zu erläutern oder experimentelle Daten zu veröffentlichen. Ich möchte einen Artikel schreiben (ich wünschte, ich könnte ihn schreiben), ohne in Zukunft Abstriche zu machen. Wir entschuldigen uns für die Unannehmlichkeiten, würden uns aber freuen, wenn Sie auf Fehler hinweisen könnten.

Recommended Posts

Unüberwachte Textklassifizierung mit Doc2Vec und k-means
Dokumentklassifizierung mit toch Text von PyTorch
k-bedeutet und Kernel k-bedeutet
Fordern Sie die Textklassifizierung von Naive Bayes mit sklearn heraus
kmeans ++ mit scikit-learn
Koordinierte Filterung mit Hauptkomponentenanalyse und K-Mittel-Clustering
Text Mining mit Python-Scraping-
Pythonbrew mit erhabenem Text
Mit und ohne WSGI
Textklassifizierung mit Convolution (CNN) und Spatial Pyramid Pooling (SPP-net)
Lerne japanische Textkategorien mit tf-idf und Random Forest ~ [Tuning]
Bildklassifizierung mit selbst erstelltem neuronalen Netzwerk von Keras und PyTorch