[PYTHON] Seq2Seq (2) ~ Achtung Model Edition ~ mit Chainer

In Sequence to Sequence (Seq2Seq), einer Art EncoderDecoder-Modell, Das Aufmerksamkeitsmodell wird vorgestellt und seine Implementierungs- und Verifizierungsergebnisse werden erläutert.

Einführung

Letztes Mal http://qiita.com/kenchin110100/items/b34f5106d5a211f4c004 Ich habe das Seq2Seq-Modell (Sequence to Sequence) mit Chainer implementiert. Dieses Mal habe ich diesem Modell ein Aufmerksamkeitsmodell hinzugefügt.

Im Folgenden werden das Aufmerksamkeitsmodell, seine Implementierungsmethode und die Überprüfungsergebnisse erläutert.

Attention Model

Was ist ein Aufmerksamkeitsmodell?

Durch Verwendung eines RNN-Netzwerks wie LSTM können Seriendaten wie Anweisungen in Merkmalsvektoren konvertiert werden.

Es ist jedoch weniger wahrscheinlich, dass die anfänglich eingegebenen Daten im endgültigen Ausgabe-Merkmalsvektor wiedergegeben werden.

Mit anderen Worten, der Satz "Mama hat sich geschminkt und einen Rock angezogen und ist in die Stadt gegangen" und der Satz "Papa hat sich geschminkt und einen Rock angezogen und ist in die Stadt gegangen" wurden fast zum gleichen Merkmalsvektor. Es bedeutet, dass es enden wird.

Das Aufmerksamkeitsmodell ist ein Mechanismus, der die zu Beginn eingegebenen Daten richtig berücksichtigt.

Sequence to Sequence with Attention Model

Die folgende Abbildung zeigt den Berechnungsablauf des zuletzt implementierten Seq2Seq-Modells.

Sequence to Sequence
seq2seq.png

(Die Abbildung unterscheidet sich geringfügig von der vorherigen)

Der blaue Teil ist der Codierer, der die Äußerung vektorisiert, und der rote Teil ist der Decodierer, der die Antwort vom Vektor ausgibt.

Wenn Sie das Aufmerksamkeitsmodell hinzufügen, sieht es wie in der folgenden Abbildung aus.

Sequence to Sequence with Attention model
attseq2seq.png

Es wird ein wenig kompliziert sein, aber der Ort, an dem [At] in der Abbildung geschrieben ist, ist das Aufmerksamkeitsmodell.

Auf der Encoderseite wird der Zwischenvektor, der jedes Mal ausgegeben wird, im Aufmerksamkeitsmodell gespeichert.

Geben Sie auf der Decoderseite den vorherigen Zwischenvektor in das Aufmerksamkeitsmodell ein. Basierend auf dem Eingabevektor nimmt das Aufmerksamkeitsmodell den gewichteten Durchschnitt der Zwischenvektoreingabe auf der Encoderseite und kehrt zurück.

Durch Eingabe des gewichteten Durchschnitts des Zwischenvektors von Encoder in Decoder ermöglicht das Aufmerksamkeitsmodell, das Wort vor, das Wort nach und überall zu beachten.

Es gibt zwei Haupttypen von Aufmerksamkeitsmodellen: Globale Aufmerksamkeit und Lokale Aufmerksamkeit.

Im Folgenden werden globale Aufmerksamkeit und lokale Aufmerksamkeit erläutert.

Global Attention

Das folgende Papier schlägt Global Attention vor.

Bahdanau, Dzmitry, Kyunghyun Cho, and Yoshua Bengio. "Neural machine translation by jointly learning to align and translate." arXiv preprint arXiv:1409.0473 (2014).

Ursprünglich wurde es in der maschinellen Übersetzung verwendet.

Das Material, das Global Attention erklärt, ist https://www.slideshare.net/yutakikuchi927/deep-learning-nlp-attention Ist leicht zu verstehen.

Es wird in Englisch sein, https://talbaumel.github.io/attention/ Ist auch leicht zu verstehen.

Der Mechanismus zum Ermitteln des gewichteten Durchschnitts der Zwischenvektoreingabe auf der Encoderseite ist unten gezeigt.

Global Attention
global_attention.png

Die Figur betrachtet einen Zustand, in dem drei Vektoren [Zwischenvektor 1], [Zwischenvektor 2] und [Zwischenvektor 3] auf der Codiererseite eingegeben werden.

In der Figur sind [eh] und [hh] lineare Kopplungsschichten, die den Vektor der Größe der verborgenen Schicht aus dem Vektor der Größe der verborgenen Schicht ausgeben, [+] ist die Addition der Vektoren und [×] ist die Multiplikation jedes Elements des Vektors. Ich bin.

[tanh] ist eine hyperbolische Tangente, die die Elemente eines Vektors von -1 nach 1 transformiert.

[hw] ist eine lineare Kopplungsschicht, die einen Skalar der Größe 1 aus der Größe der verborgenen Schicht ausgibt.

[soft max] ist eine SoftMax-Funktion, die die eingegebenen Werte so normalisiert, dass die Summe 1 ist.

Der durch [Soft max] berechnete Wert wird als Gewicht des gewichteten Durchschnitts verwendet, und das Ergebnis der Verwendung des gewichteten Durchschnitts des Zwischenvektors wird ausgegeben.

So funktioniert Global Attention.

Local Attention

Die Papiere, für die lokale Aufmerksamkeit vorgeschlagen wurde, sind wie folgt

Luong, Minh-Thang, Hieu Pham, and Christopher D. Manning. "Effective approaches to attention-based neural machine translation." arXiv preprint arXiv:1508.04025 (2015).

Dies ist auch ein maschinelles Übersetzungspapier.

Das Referenzmaterial ist https://www.slideshare.net/yutakikuchi927/deep-learning-nlp-attention ist.

Unten finden Sie ein Berechnungsflussdiagramm der lokalen Aufmerksamkeit.

Local Attention
local_attention.png

Weitere Netzwerke wurden zu Global Attention hinzugefügt.

Der Hauptunterschied ist das Netzwerk auf der rechten Seite.

[ht] ist eine lineare Verknüpfung, die einen verborgenen Schichtgrößenvektor aus einem verborgenen Schichtgrößenvektor ausgibt, und [tanh] skaliert die Elemente des Vektors wie zuvor von -1 auf 1.

[tw] ist eine linear gekoppelte Schicht, die einen verborgenen Schichtgrößenvektor in einen Skalar umwandelt, und [sigmoid] ist eine Sigmoidfunktion, die den Eingabewert von 0 auf 1 skaliert. Daher ist der bisher eingegebene Vektor ein Skalar im Bereich von 0 bis 1.

Als nächstes werde ich in der Abbildung erklären, was Sie mit [ga] machen. Die Berechnung von ga ist wie folgt.

output = \exp\bigl(-\frac{(s - input * Len(S))^2}{\sigma^2}\bigl)

Während $ input $ ein von 0 bis 1 skalierter Skalar ist, ist $ Len (S) $ die Anzahl der vom Codierer eingegebenen Zwischenvektoren und $ s $ die Reihenfolge der Zwischenschichtvektoren ([Zwischenvektor 1]]. Wenn es 1 ist, repräsentiert es 2) wenn es [Zwischenvektor 2] ist.

Wenn der von der Sigmoidfunktion ausgegebene Wert 0,1 ist, ist [ga] ein großer Wert, wenn der Zwischenvektor 1 ist, und ein kleiner Wert, wenn der Zwischenvektor 3 ist.

Durch Multiplizieren dieser Ausgabe mit dem von Global Attention berechneten Gewicht ist es möglich, sich stärker auf einen bestimmten Zwischenvektor zu konzentrieren.

Implementierung

Ich habe es wie zuvor mit Chainer implementiert. Der Encoder-Teil ist der gleiche wie für Seq2Seq.

Der Code, auf den ich mich bezog, stammt von oda. Vielen Dank. https://github.com/odashi/chainer_examples

Attention

Ich habe Global Attention implementiert. Der Code lautet wie folgt

attention.py



class Attention(Chain):
    def __init__(self, hidden_size, flag_gpu):
        """
Aufmerksamkeitsinstanziierung
        :param hidden_size:Versteckte Ebenengröße
        :param flag_gpu:Gibt an, ob eine GPU verwendet werden soll
        """
        super(Attention, self).__init__(
            #Eine lineare Kopplungsschicht, die den Vorwärtscodierer-Zwischenvektor in einen verborgenen Schichtgrößenvektor umwandelt
            fh=links.Linear(hidden_size, hidden_size),
            #Eine lineare Kopplungsschicht, die den Zwischenvektor des Rückwärtscodierers in einen verborgenen Schichtgrößenvektor umwandelt
            bh=links.Linear(hidden_size, hidden_size),
            #Eine lineare Kopplungsschicht, die den Zwischenvektor des Decoders in einen versteckten Schichtgrößenvektor umwandelt
            hh=links.Linear(hidden_size, hidden_size),
            #Lineare Kopplungsschicht zum Konvertieren versteckter Schichtgrößenvektoren in Skalare
            hw=links.Linear(hidden_size, 1),
        )
        #Merken Sie sich die Größe der ausgeblendeten Ebene
        self.hidden_size = hidden_size
        #Verwenden Sie numpy, wenn Sie bei Verwendung der GPU kein cupy verwenden
        if flag_gpu:
            self.ARR = cuda.cupy
        else:
            self.ARR = np

    def __call__(self, fs, bs, h):
        """
Aufmerksamkeitsberechnung
        :param fs:Eine Liste von Forward-Encoder-Zwischenvektoren
        :param bs:Liste der Zwischenvektoren des Umkehrcodierers
        :param h:Zwischenvektorausgabe durch Decoder
        :return:Gewichteter Durchschnitt des Zwischenvektors des Vorwärtscodierers und gewichteter Durchschnitt des Zwischenvektors des Rückwärtscodierers
        """
        #Denken Sie an die Größe der Mini-Charge
        batch_size = h.data.shape[0]
        #Initialisieren der Liste zum Aufzeichnen von Gewichten
        ws = []
        #Initialisieren Sie den Wert, um den Gesamtwert des Gewichts zu berechnen
        sum_w = Variable(self.ARR.zeros((batch_size, 1), dtype='float32'))
        #Gewichtsberechnung unter Verwendung des Zwischenvektors des Encoders und des Zwischenvektors des Decoders
        for f, b in zip(fs, bs):
            #Gewichtsberechnung mit Vorwärtscodierer-Zwischenvektor, Rückwärtscodierer-Zwischenvektor, Decoder-Zwischenvektor
            w = functions.tanh(self.fh(f)+self.bh(b)+self.hh(h))
            #Normalisieren Sie mit der Softmax-Funktion
            w = functions.exp(self.hw(w))
            #Notieren Sie das berechnete Gewicht
            ws.append(w)
            sum_w += w
        #Initialisierung des ausgegebenen gewichteten Durchschnittsvektors
        att_f = Variable(self.ARR.zeros((batch_size, self.hidden_size), dtype='float32'))
        att_b = Variable(self.ARR.zeros((batch_size, self.hidden_size), dtype='float32'))
        for f, b, w in zip(fs, bs, ws):
            #Normalisiert, so dass die Summe der Gewichte 1 ist.
            w /= sum_w
            #Gewicht*Fügen Sie den Zwischenvektor von Encoder zum Ausgabevektor hinzu
            att_f += functions.reshape(functions.batch_matmul(f, w), (batch_size, self.hidden_size))
            att_b += functions.reshape(functions.batch_matmul(b, w), (batch_size, self.hidden_size))
        return att_f, att_b

In der Erklärung wurde nur ein Encoder verwendet, aber tatsächlich ist es üblich, zwei Typen von Encodern zu verwenden, den Vorwärtscodierer und den Rückwärtscodierer im Aufmerksamkeitsmodell.

Bei der Berechnung der Aufmerksamkeit übergeben wir also zwei Listen von Zwischenvektoren, die vom Vorwärtscodierer berechnet wurden, und eine Liste von Zwischenvektoren, die vom Rückwärtscodierer berechnet wurden.

Decoder

Im Gegensatz zu Seq2Seq sind die vom Decoder eingegebenen Werte drei, der Wortvektor, der vom Decoder berechnete Zwischenvektor und der gewichtete Durchschnitt des Zwischenvektors des Codierers. Also schreibe ich die Implementierung von Decoder neu.

att_decoder.py



class Att_LSTM_Decoder(Chain):
    def __init__(self, vocab_size, embed_size, hidden_size):
        """
Decoder-Instanziierung für das Aufmerksamkeitsmodell
        :param vocab_size:Anzahl der Vokabeln
        :param embed_size:Wortvektorgröße
        :param hidden_size:Versteckte Ebenengröße
        """
        super(Att_LSTM_Decoder, self).__init__(
            #Ebene zum Konvertieren von Wörtern in Wortvektoren
            ye=links.EmbedID(vocab_size, embed_size, ignore_label=-1),
            #Eine Ebene, die einen Wortvektor in einen Vektor umwandelt, der viermal so groß ist wie die verborgene Ebene
            eh=links.Linear(embed_size, 4 * hidden_size),
            #Eine Ebene, die den Zwischenvektor des Decoders in einen Vektor umwandelt, der viermal so groß ist wie die verborgene Ebene
            hh=links.Linear(hidden_size, 4 * hidden_size),
            #Eine Ebene, die den gewichteten Durchschnitt des Zwischenvektors des Vorwärtscodierers in einen Vektor umwandelt, der viermal so groß ist wie die verborgene Ebene
            fh=links.Linear(hidden_size, 4 * hidden_size),
            #Eine Ebene, die den gewichteten Durchschnitt des Zwischenvektors des Vorwärtscodierers in einen Vektor umwandelt, der viermal so groß ist wie die verborgene Ebene
            bh=links.Linear(hidden_size, 4 * hidden_size),
            #Eine Ebene, die einen versteckten Ebenengrößenvektor in die Größe eines Wortvektors konvertiert
            he=links.Linear(hidden_size, embed_size),
            #Ebene zum Konvertieren des Wortvektors in einen Vokabulargrößenvektor
            ey=links.Linear(embed_size, vocab_size)
        )

    def __call__(self, y, c, h, f, b):
        """
Decoderberechnung
        :param y:Wörter, die in Decoder eingegeben werden müssen
        :param c:Interner Speicher
        :param h:Decoder-Zwischenvektor
        :param f:Gewichteter Durchschnitt des Forward-Encoders, berechnet nach dem Aufmerksamkeitsmodell
        :param b:Gewichteter Durchschnitt des Rückwärtscodierers, berechnet durch das Aufmerksamkeitsmodell
        :return:Wörterbuch der Vokabulargröße, aktualisierter interner Speicher, aktualisierter Zwischenvektor
        """
        #Konvertieren Sie Wörter in Wortvektoren
        e = functions.tanh(self.ye(y))
        #LSTM unter Verwendung eines Wortvektors, Zwischenvektors des Decoders, Aufmerksamkeit des Vorwärtscodierers, Aufmerksamkeit des Rückwärtscodierers
        c, h = functions.lstm(c, self.eh(e) + self.hh(h) + self.fh(f) + self.bh(b))
        #Konvertieren Sie die von LSTM ausgegebene Zwischenvektorversion in einen lexikalischen Größenvektor
        t = self.ey(functions.tanh(self.he(h)))
        return t, c, h

Die Verwendung eines Vektors, der viermal so groß ist wie die verborgene Ebene, ist der gleiche Grund, den ich beim letzten Mal erklärt habe.

Wir haben die Schichten [fh] und [bh] hinzugefügt, um den gewichteten Durchschnitt der durch Attention berechneten Zwischenvektoren des Encoders zu verwenden, aber ansonsten sind sie gleich.

Seq2Seq with Attention

Das Modell, das Encoder, Decoder und Attention kombiniert, ist wie folgt.

att_seq2seq.py



class Att_Seq2Seq(Chain):
    def __init__(self, vocab_size, embed_size, hidden_size, batch_size, flag_gpu=True):
        """
        Seq2Seq +Aufmerksamkeitsinstanziierung
        :param vocab_size:Anzahl der Vokabeln
        :param embed_size:Wortvektorgröße
        :param hidden_size:Versteckte Ebenengröße
        :param batch_size:Mini-Chargengröße
        :param flag_gpu:Gibt an, ob eine GPU verwendet werden soll
        """
        super(Att_Seq2Seq, self).__init__(
            #Vorwärtscodierer
            f_encoder = LSTM_Encoder(vocab_size, embed_size, hidden_size),
            #Rückwärtsgeber
            b_encoder = LSTM_Encoder(vocab_size, embed_size, hidden_size),
            # Attention Model
            attention = Attention(hidden_size, flag_gpu),
            # Decoder
            decoder = Att_LSTM_Decoder(vocab_size, embed_size, hidden_size)
        )
        self.vocab_size = vocab_size
        self.embed_size = embed_size
        self.hidden_size = hidden_size
        self.batch_size = batch_size

        #Cupy bei Verwendung der GPU, numpy bei Nichtgebrauch
        if flag_gpu:
            self.ARR = cuda.cupy
        else:
            self.ARR = np

        #Initialisieren Sie die Liste, um den Vorwärtscodierer-Zwischenvektor und den Rückwärtscodierer-Zwischenvektor zu speichern
        self.fs = []
        self.bs = []

    def encode(self, words):
        """
Geberberechnung
        :param words:Eine aufgezeichnete Liste von Wörtern, die für Ihre Eingabe verwendet werden sollen
        :return: 
        """
        #Interner Speicher, Initialisierung des Zwischenvektors
        c = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        h = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        #Berechnen Sie zunächst den Vorwärtscodierer
        for w in words:
            c, h = self.f_encoder(w, c, h)
            #Notieren Sie den berechneten Zwischenvektor
            self.fs.append(h)

        #Interner Speicher, Initialisierung des Zwischenvektors
        c = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        h = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        #Reverse Encoder Berechnung
        for w in reversed(words):
            c, h = self.b_encoder(w, c, h)
            #Notieren Sie den berechneten Zwischenvektor
            self.bs.insert(0, h)

        #Interner Speicher, Initialisierung des Zwischenvektors
        self.c = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        self.h = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))

    def decode(self, w):
        """
Decoderberechnung
        :param w:Mit Decoder einzugebende Wörter
        :return:Voraussagendes Wort
        """
        #Berechnen Sie den gewichteten Durchschnitt der mittleren Ebene des Encoders mithilfe des Aufmerksamkeitsmodells
        att_f, att_b = self.attention(self.fs, self.bs, self.h)
        #Unter Verwendung des Decoder-Zwischenvektors Vorwärtsaufmerksamkeit, Rückwärtsaufmerksamkeit
        #Berechnung des nächsten Zwischenvektors, des internen Speichers und des vorhergesagten Wortes
        t, self.c, self.h = self.decoder(w, self.c, self.h, att_f, att_b)
        return t

    def reset(self):
        """
Instanzvariablen initialisieren
        :return: 
        """
        #Interner Speicher, Initialisierung des Zwischenvektors
        self.c = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        self.h = Variable(self.ARR.zeros((self.batch_size, self.hidden_size), dtype='float32'))
        #Initialisierung der Liste, die den Zwischenvektor von Encoder aufzeichnet
        self.fs = []
        self.bs = []
        #Gradienteninitialisierung
        self.zerograds()

Es werden insgesamt drei LSTMs verwendet: Vorwärtscodierer, Rückwärtscodierer und Decodierer.

Die Vorwärtsberechnung und die Zugberechnung sind die gleichen wie für Seq2Seq.

Der erstellte Code ist https://github.com/kenchin110100/machine_learning/blob/master/sampleAttSeq2Seq.py Es ist in.

Experiment

Korpus

Ich habe den Dialogfehlerkorpus wie beim letzten Mal verwendet. https://sites.google.com/site/dialoguebreakdowndetection/chat-dialogue-corpus

Versuchsergebnis

Es gibt 4 Arten von Äußerungen wie zuvor

Lassen Sie uns die Antwort für jede Epoche sehen.

Erste 1 Epoche

Sprechen:Guten Morgen=>Antwort:  ['damit', 'ist', 'Hallo', '</s>']
Sprechen:Wie geht's?=>Antwort:  ['Ja', '、', 'Was', 'Zu', 'Sie sehen', 'Hand', 'Masu', 'Oder', '?', '</s>']
Sprechen:Ich bin hungrig=>Antwort:  ['Ja', '</s>']
Sprechen:Es ist heiß heute=>Antwort:  ['Ja', '、', 'Was', 'Zu', 'Sie sehen', 'Hand', 'Masu', 'Oder', '?', '</s>']

Hattest du so einen bösen Blick ...

3Epoch

Sprechen:Guten Morgen=>Antwort:  ['Hallo.', '</s>']
Sprechen:Wie geht's?=>Antwort:  ['damit', 'ist', '</s>']
Sprechen:Ich bin hungrig=>Antwort:  ['Hitzschlag', 'Zu', 'Qi', 'Zu', 'Anfügen', 'Hand', 'Masu', 'Oder', '?', '</s>']
Sprechen:Es ist heiß heute=>Antwort:  ['Hitzschlag', 'Zu', 'Qi', 'Zu', 'Anfügen', 'Abwesend', 'Hmm', 'ist', 'Oder', '?', '</s>']

5Epoch

Sprechen:Guten Morgen=>Antwort:  ['Vielen Dank', '</s>']
Sprechen:Wie geht's?=>Antwort:  ['Wassermelone', 'Ist', 'Mögen', 'ist', 'Hallo', '</s>']
Sprechen:Ich bin hungrig=>Antwort:  ['Hitzschlag', 'Zu', 'Qi', 'Zu', 'Anfügen', 'Hand', 'Wollen', 'ist', 'Oder', '?', '</s>']
Sprechen:Es ist heiß heute=>Antwort:  ['Hitzschlag', 'Zu', 'Qi', 'Zu', 'Anfügen', 'Hand', 'Wollen', 'ist', 'Oder', '?', '</s>']

Ich weiß bereits über Hitzschlag ...

7Epoch

Sprechen:Guten Morgen=>Antwort:  ['Guten Abend', '</s>']
Sprechen:Wie geht's?=>Antwort:  ['Wassermelone', 'Ist', 'Ich liebe dich', 'ist', 'Hallo', '</s>']
Sprechen:Ich bin hungrig=>Antwort:  ['Bai', 'Bai', '</s>']
Sprechen:Es ist heiß heute=>Antwort:  ['Hitzschlag', 'Zu', 'Qi', 'Zu', 'Anfügen', 'Abwesend', 'Hmm', 'ist', 'Oder', '?', '</s>']

Guten Morgen => Guten Abend, es ist schrecklich ...

Ich habe das Gefühl, dass die Genauigkeit schlechter ist als die von Seq2Seq ...

Wie bei Seq2Seq konnte ich die Frage "Wie geht es dir?" Nicht gut beantworten. Vielleicht wurde das Wort "Ton" im Korpus nicht verwendet.

Da es sich bei dem Original um ein Dialogfehlerkorpus handelt, wird das Ergebnis des Fehlers zurückgegeben, dh es kann sein, dass Sie damit gut lernen ...

Der Übergang des Gesamtverlustwertes und der Vergleich der Berechnungszeit werden am Ende zusammengefasst.

Fazit

Ich habe das Seq2Seq + Attention Model mit Chainer berechnet.

Ich hatte das Gefühl, dass die Berechnungszeit im Vergleich zu Seq2Seq allein extrem lang war. Der Vergleich dieses Gebiets wird ...

Nächstes Mal werde ich CopyNet implementieren ... Ich möchte es tun.

Recommended Posts

Seq2Seq (2) ~ Achtung Model Edition ~ mit Chainer
Seq2Seq (3) ~ CopyNet Edition ~ mit Chainer
Seq2Seq (1) mit Chainer
Ich habe versucht, Attention Seq2Seq mit PyTorch zu implementieren
Achtung Seq2 Führen Sie das Dialogmodell mit Seq aus
Laden Sie das Kaffeemodell mit Chainer und klassifizieren Sie die Bilder
Bilderkennung mit Caffe Model Chainer Yo!
Verwenden Sie Tensorboard mit Chainer
Regression mit einem linearen Modell
USB-Boot mit Raspberry Pi 4 Modell B (3) LVM Edition
Tech Circle ML # 8 Chainer mit wiederkehrendem neuronalen Sprachmodell
MVC-Model Edition, um nur mit Voreingenommenheit von 0 zu lernen
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Modellversion)
Versuchen Sie, RBM mit Chainer zu implementieren.
Lernen Sie mit Chainer elliptische Bahnen
Verwendung von Chainer mit Jetson TK1
Neuronales Netz beginnend mit Chainer
Bedingte GAN mit Chainer implementiert
Bildunterschriftengenerierung mit Chainer
Kalibrieren Sie das Modell mit PyCaret
SmoothGrad mit Chainer v2 implementiert
Deep Embedded Clustering mit Chainer 2.0