[PYTHON] Lassen Sie uns die Emotionen von Tweet mit Chainer (2.) analysieren.

Überblick

Letztes Mal ist die grundlegende Verwendung von Chainer, die Implementierung von MLP (Multilayer Perceptron) und die Anzahl der Knoten der vollständig verbundenen Schicht aus der Faltungsschicht von CNN. Ich habe die dafür notwendige Berechnungsformel eingeführt.

Dieses Mal werde ich die tatsächlichen Twitter-Daten lesen und ein CNN erstellen.

Faltungsneuronales Netzwerk

Die Erklärung des Faltungsnetzwerks war [hier] leicht zu verstehen (http://tkengo.github.io/blog/2016/03/11/understanding-convolutional-neural-networks-for-nlp/).

image

Ein Filter wird auf die zweidimensionalen Bilddaten angewendet, um die Merkmale zu komprimieren. Danach wird ein Pooling durchgeführt, um die Feature-Menge weiter zu extrahieren. Wahrscheinlich gibt es nicht einen Filtertyp, aber für die Anzahl der Blätter, die Sie ausgeben möchten, werden unterschiedliche Filter angewendet.

Ziel

Dieser Artikel unter Bezugnahme auf [http://qiita.com/hogefugabar/items/93fcb2bc27d7b268cbe6) Ich werde darüber nachdenken, es nachzuahmen.

Überblick über die Verarbeitung

Der Umriss des Prozesses ist wie folgt.

  1. Lesen Sie Tweet-Daten
  2. Word Embed (diesmal wird Word2Vec verwendet)
  3. Lern- / Testdatenaufteilung
  4. Definition von CNN
  5. Lernen mit CNN
  6. CNN-Prognose

Die Definition und das Lernen von CNN verwenden die folgende in diesem Artikel beschriebene Methode.

image

Diese Abbildung zeigt den Faltungs- und Pooling-Prozess für einen einzelnen Satz, wobei $ d $ die Dimension des Wortvektors und $ s $ die Anzahl der Wörter im Satz in der großen Matrix ganz links ist. Und die Filtergröße ist keine symmetrische Matrix, sondern eine asymmetrische Matrix mit $ d × m $ Dimensionen.

Ich habe es jedoch selbst nach dem Lesen der Zeitung nicht verstanden, aber $ s $ ist für jeden Satz anders. Wenn ich mich also gefragt habe, wie das geht, dieser Artikel / items / 93fcb2bc27d7b268cbe6) verwendet die maximale Anzahl von Wörtern für jeden Satz, der in allen Tweets vorkommt. Imitieren Sie dies also.

Datenerfassung

Holen Sie sich die Tweet-Daten (https://raw.githubusercontent.com/satwantrana/CharSCNN/master/tweets_clean.txt). In den Daten ist die erste Spalte das Flag von [0,1] und die zweite Spalte ist der Tweet in Englisch.

Word Embed

Ich möchte den Satz in einem zweidimensionalen Bildformat halten, daher werde ich ihn in eine verteilte Darstellung ändern. Dieses Mal funktionierte die mit Chainer gelieferte Embed-ID nicht, daher verwende ich Word2Vec aus dem Gensim-Paket.

Weisen Sie Word zunächst eine ID aus den Textdaten zu.

#! -*- coding:utf-8 -*-

def read(inp_file,num_sent=None):
        f_in = open(inp_file, 'r')
        lines = f_in.readlines()

        words_map = {}
        word_cnt = 0

        k_wrd = 5 #Word-Kontextfenster

        y = []
        x_wrd = []

        if num_sent is None:
            num_sent = len(lines)
            max_sen_len = 0
        else:
            max_sen_len, num_sent = 0, num_sent


        words_vocab_mat = []

        token_list = []

        for line in lines[:num_sent]:
            words = line[:-1].split()
            tokens = words[1:]
            y.append(int(float(words[0])))
            max_sen_len = max(max_sen_len,len(tokens))
            for token in tokens:
                if token not in words_map:
                    words_map[token] = word_cnt
                    token_list.append(token)
                    word_cnt += 1
            words_vocab_mat.append(tokens)

        cnt = 0
        for line in lines[:num_sent]:
            words = line[:-1].split()
            cnt += 1
            tokens = words[1:]
            word_mat = [-1] * (max_sen_len+k_wrd-1)

            for i in xrange(len(tokens)):
                word_mat[(k_wrd/2)+i] = words_map[tokens[i]]
            x_wrd.append(word_mat)
        max_sen_len += k_wrd-1

        # num_sent:Anzahl der Dokumente
        # word_cnt:Anzahl der Worttypen
        # max_sen_len:Maximale Länge des Dokuments
        # x_wrd:Anzahl der Zeilen in der ID-Spalte des Eingabeworts:Anzahl der Sätze(num_sent)Anzahl der Spalten:Maximale Länge des Dokuments(max_sen_len)
        # k_wrd: window size
        # words_map : key = word,value = id
        # y: 1 or 0 (i.e., positive or negative)
        # words_vocab_mat :Zerlegter Satz, Anzahl der Zeilen ist Anzahl der Sätze, Anzahl der Spalten ist variabel und Anzahl der Wörter
        # token_list :Token-Liste, Index entspricht ID
        data = (num_sent, word_cnt, max_sen_len, k_wrd, x_wrd, y,words_map,words_vocab_mat,token_list)
        return data

(num_sent, word_cnt, max_sen_len, k_wrd, x_wrd, y,words_map,sentences,token_list) = load.read("data/tweets_clean.txt",10000)

x_wrd ist eine Matrix aus der Anzahl der Sätze x der maximalen Dokumentlänge, und jedes Element ist die ID des angezeigten Wortes. Bereiten Sie words_map, token_list und words_vocab_mat so vor, wie Sie sie später benötigen.

Verwenden Sie als Nächstes Word2Vec, um eine Vektordarstellung für jedes Wort zu erhalten, und erstellen Sie dann eine "Satzbildmatrix" (willkürlich angehängt).

    """Erstellen Sie mit Word2Vec einen Wortvektorraum"""
    word_dimension = 200
    from gensim.models import Word2Vec
    model_w2v = Word2Vec(sentences,seed=123,size=word_dimension,min_count=0,window=5)
    sentence_image_matrix = np.zeros((len(sentences),1,word_dimension,max_sen_len)) #Initialisierung der Satzbildmatrix für die Faltung

    """x_Generieren Sie einen Vektor für wrd"""
    for i in range(0,len(x_wrd)):
        tmp_id_list = x_wrd[i,:]
        for j in range(0,len(tmp_id_list)):
            """Biegen Sie für eine Linie"""
            id = tmp_id_list[j]
            if id == -1:
                """Keine Information"""
                sentence_image_matrix[i,0,:,j] = [0.] * word_dimension #0 Vektor einfügen
            else:
                target_word = token_list[id]
                sentence_image_matrix[i,0,:,j] = model_w2v[target_word]

Satz_Bildmatrix ist definiert als ein 4-dimensionaler Tensor mit der Größe (Anzahl der Sätze, 1, Vektordimension = 200, maximale Satzlänge).

Datenaufteilung lernen / testen

Wie ich zum ersten Mal erfahren habe, kann sklearns train_test_split auch für 4-dimensionale Tensoren verwendet werden. Wahrscheinlich, weil ich nur die erste Dimension betrachte.

    """Teilen Sie in Trainingsdaten und Testdaten"""
    sentence_image_matrix = np.array(sentence_image_matrix,dtype=np.float32)
    N = len(sentence_image_matrix)
    t_n = 0.33
    x_train,x_test,y_train,y_test = train_test_split(sentence_image_matrix,y,test_size=t_n,random_state=123)

Definition von CNN

Das Problem ist die Definition von CNN. In diesem Artikel verwenden wir einen asymmetrischen Filter, und das Pooling ist ebenfalls asymmetrisch, daher müssen wir dies berücksichtigen.

Dann sieht es so aus.

class CNNFiltRow(ChainerClassifier):
    """
Ein Muster, das alle Zeilenrichtungen von CNN in Spaltenrichtung als Filter verschiebt
    """

    def _setup_network(self, **params):
        self.input_dim = params["input_dim"] #Spaltenweise Abmessungen eines einzelnen Bildes
        self.in_channels = params["in_channels"] #input channels : default = 1
        self.out_channels = params["out_channels"] #out_channels :Irgendein
        self.row_dim = params["row_dim"] #Zeilenrichtungsdimension eines Bildes=Es wird die Anzahl der Filterzeilen
        self.filt_clm = params["filt_clm"] #Anzahl der Filterspalten
        self.pooling_row = params["pooling_row"] if params.has_key("pooling_row") else 1 #Anzahl der Poollinien: default = 1
        self.pooling_clm = params["pooling_clm"] if params.has_key("pooling_clm") else int(self.input_dim - 2 * math.floor(self.filt_clm/2.)) #Anzahl der Pooling-Spalten: default = math.floor((self.input_dim - 2 * math.floor(self.filt_clm/2.))
        self.batch_size = params["batch_size"] if params.has_key("batch_size") else 100
        self.hidden_dim = params["hidden_dim"]
        self.n_classes = params["n_classes"]

        self.conv1_out_dim = math.floor((self.input_dim - 2 * math.floor(self.filt_clm/2.))/self.pooling_clm)
        network = FunctionSet(
            conv1 = F.Convolution2D(self.in_channels,self.out_channels,(self.row_dim,self.filt_clm)), #Filter asymmetrisch gemacht
            l1=F.Linear(self.conv1_out_dim*self.out_channels, self.hidden_dim),
            l2=F.Linear(self.hidden_dim, self.hidden_dim),
            l3=F.Linear(self.hidden_dim, self.n_classes),
        )
        return network

    def forward(self, x, train=True):
        h = F.max_pooling_2d(F.relu(self.network.conv1(x)), (self.pooling_row,self.pooling_clm))
        h1 = F.dropout(F.relu(self.network.l1(h)),train=train)
        h2 = F.dropout(F.relu(self.network.l2(h1)),train=train)
        y = self.network.l3(h2)
        return y

    def output_func(self, h):
        return F.softmax(h)

    def loss_func(self, y, t):
        return F.softmax_cross_entropy(y, t)

    def fit(self, x_data, y_data):
        batchsize = self.batch_size
        N = len(y_data)
        for loop in range(self.n_iter):
            perm = np.random.permutation(N)
            sum_accuracy = 0
            sum_loss = 0
            for i in six.moves.range(0, N, batchsize):
                x_batch = x_data[perm[i:i + batchsize]]
                y_batch = y_data[perm[i:i + batchsize]]
                x = Variable(x_batch)
                y = Variable(y_batch)
                self.optimizer.zero_grads()
                yp = self.forward(x)
                loss = self.loss_func(yp,y)
                loss.backward()
                self.optimizer.update()
                sum_loss += loss.data * len(y_batch)
                sum_accuracy += F.accuracy(yp,y).data * len(y_batch)
            if self.report > 0 and loop % self.report == 0:
                print('loop={}, train mean loss={} , train mean accuracy={}'.format(loop, sum_loss / N,sum_accuracy / N))

        return self

    def fit_test(self, x_data, y_data,x_test,y_test):
        batchsize = self.batch_size
        N = len(y_data)
        Nt = len(y_test)
        train_ac = []
        test_ac = []
        for loop in range(self.n_iter):
            perm = np.random.permutation(N)
            permt = np.random.permutation(Nt)
            sum_accuracy = 0
            sum_loss = 0

            sum_accuracy_t = 0

            """Lernphase"""
            for i in six.moves.range(0, N, batchsize):
                x_batch = x_data[perm[i:i + batchsize]]
                y_batch = y_data[perm[i:i + batchsize]]
                x = Variable(x_batch)
                y = Variable(y_batch)
                self.optimizer.zero_grads()
                yp = self.forward(x)
                loss = self.loss_func(yp,y)
                loss.backward()
                self.optimizer.update()
                sum_loss += loss.data * len(y_batch)
                sum_accuracy += F.accuracy(yp,y).data * len(y_batch)

            """Testphase"""
            for i in six.moves.range(0,Nt,batchsize):
                x_batch = x_test[permt[i:i + batchsize]]
                y_batch = y_test[permt[i:i + batchsize]]
                x = Variable(x_batch)
                y = Variable(y_batch)
                yp = self.forward(x,False)
                sum_accuracy_t += F.accuracy(yp,y).data * len(y_batch)

            if self.report > 0 and loop % self.report == 0:
                print('loop={}, train mean loss={} , train mean accuracy={} , test mean accuracy={}'.format(loop, sum_loss / N,sum_accuracy / N,sum_accuracy_t / Nt))

            train_ac.append(sum_accuracy / N)
            test_ac.append(sum_accuracy_t / Nt)

        return self,train_ac,test_ac

Weitere Informationen zum Chainer Classifier finden Sie in Vorheriger Artikel.

CNN lernen

Ich wollte auch die Genauigkeit der Testdaten sehen, also habe ich die Methode fit_test hinzugefügt.

    """CNN-Filterzeile lernen"""
    n_iter = 200
    report = 5
    params = {"input_dim":max_sen_len,"in_channels":1,"out_channels":20,"row_dim":word_dimension,"filt_clm":3,"batch_size":100,"hidden_dim":300,"n_classes":2}
    cnn = CNNFiltRow(n_iter=n_iter,report=report,**params)
    cnn,train_ac,test_ac = cnn.fit_test(x_train,y_train,x_test,y_test)

Unten sehen Sie eine grafische Darstellung der Genauigkeit während des Trainings und der Genauigkeit der Testdaten. Es scheint, dass das Überlernen bei etwa 100 beginnt. Dennoch ist der Eindruck, dass die Generalisierungsleistung hoch ist.

image

CNN-Prognose

Wenn Sie Testdaten in das endgültige Modell einfügen und jeden Index ausgeben, sieht dies wie folgt aus.

[CNN]P AUC: 0.80 Pres: 0.66 Recl: 0.89 Fscr: 0.76

Der F-Wert betrug 0,76 und die AUC 0,8, was ziemlich gut war.

Vergleichen Sie mit anderen Modellen

Machen Sie dasselbe mit Random Forest und MLP (Multilayer Perceptron) als Benchmark. Da die Eingabedaten in diesem Fall nicht zweidimensional sind, werden sie wie MNIST eindimensional korrigiert.

Infolgedessen sind verschiedene Indikatoren für ähnliche Testdaten wie folgt.

[RF ]P AUC: 0.71 Pres: 0.65 Recl: 0.60 Fscr: 0.62
[MLP]P AUC: 0.71 Pres: 0.64 Recl: 0.69 Fscr: 0.67
[CNN]P AUC: 0.80 Pres: 0.66 Recl: 0.89 Fscr: 0.76

Dieser überwältigende Leistungsunterschied von CNN ...

Zusammenfassung

Recommended Posts

Lassen Sie uns die Emotionen von Tweet mit Chainer (2.) analysieren.
Lassen Sie uns die Emotionen von Tweet mit Chainer (1.) analysieren.
Lassen Sie uns die Daten der Fragebogenumfrage analysieren [4 .: Emotionsanalyse]
Lassen Sie uns jetzt die Mehrdeutigkeit des Bindestrichs (-) des Befehls su beseitigen! !!
Lassen Sie uns die Emotionen von Tweet mit Chainer (2.) analysieren.
Lassen Sie uns die Emotionen von Tweet mit Chainer (1.) analysieren.
Lassen Sie uns die Karte mit der Grundkarte anzeigen
Lassen Sie uns den Gewinner des Bingo bestimmen
Ich möchte die Gefühle von Menschen analysieren, die sich treffen und zittern wollen
Informationen zum Verhalten von enable_backprop von Chainer v2
Implementierung eines Dialogsystems mit Chainer [seq2seq]
Tweet mit der Twitter-API in Python
Implementierung von "verschwommenen" neuronalen Netzen mit Chainer
Untersuchen wir den Mechanismus von Kaijis Chinchirorin
Verkürzung der Analysezeit von Openpose mithilfe von Sound
Abschätzung der Wirkung von Maßnahmen anhand von Neigungswerten
Überprüfen Sie den Typ der von Ihnen verwendeten Variablen
[Python] Lassen Sie uns das Modul regelmäßig nach Zeitplan ausführen
Exklusive Veröffentlichung der Django App mit ngrok
Lassen Sie uns Emotionen mithilfe der Emotions-API in Python beurteilen
Versuchen Sie es mit dem Sammlungsmodul (ChainMap) von python3
Bestimmen Sie die Anzahl der Klassen mithilfe der Starges-Formel
Ich habe versucht, den Bildfilter von OpenCV zu verwenden
Überprüfen Sie den Status der Daten mit pandas_profiling
Scraping der Gewinndaten von Zahlen mit Docker
Erklären des auf der PyCon 2016 angekündigten Chat-Bots aus der Codebasis (Chat-Antwort mit Chainer)