[PYTHON] Versuchen Sie, Piktogramm-Schriftarten mit Keras zu klassifizieren

Der Manga-Künstler Masayuki Kitamichi hat die Schrift "Kitamiji 222" zum Gedenken an "Cat Day" am 22. Februar produziert und veröffentlicht.

http://kitamichi.sub.jp/Sites/iblog/C513573485/E937677024/ (Einführungsartikel: http://www.forest.impress.co.jp/docs/review/20160303_746474.html)

Überprüfen Sie zunächst die Lizenz.

◆ Informationen zur Verwendung

"Kitamiji 222" ist Freeware. Wenn es nicht für den kommerziellen Gebrauch bestimmt ist, können Sie es ohne Einschränkungen frei verwenden. Bitte verkaufen, verteilen oder verarbeiten Sie den "Font File Body" jedoch nicht.

Das Copyright von "Kitamiji 222" liegt bei Masayuki Kitado. Wir sind nicht verantwortlich für Computer oder andere Probleme, die durch die Verwendung von Schriftarten verursacht werden.

(Dieses Mal habe ich das Schriftbild ausgeschnitten und es als Daten für maschinelles Lernen verwendet, aber ich denke, dass es nicht der Verarbeitung des "Schriftdateikörpers" entspricht. → Herr Kitamichi stimmte der Verwendung dieser Schrift zu.)

Zum Beispiel werden "aiueo" und "kakikukeko" wie folgt angezeigt. ** AIUEO ** a_gyo.PNG

** Kakikukeko ** ka_gyo.PNG

Auf diese Weise wird der Unterschied in den Vokalen durch die Richtung des Katzengesichts ausgedrückt, und der Unterschied in den Konsonanten wird durch den Unterschied im Haarmuster ausgedrückt. Intuitiv hatte ich das Gefühl, dass die Erkennung des Vokals "aiueo" mit einem aus einem neuronalen Netz bestehenden Klassifikator relativ einfach erfolgen kann, also habe ich dies versucht. ("A" und "e" ("ka" und "ke") sehen ein wenig ähnlich aus, aber es scheint ein wenig schwierig zu klassifizieren.)

Da "Kitamiji 222" in TrueType-Schriftart bereitgestellt wird, wurde die Arbeit im folgenden Ablauf ausgeführt.

  1. Mit "Jupyter (ipython) Notebook" + Python 3-Kernel bis zur Konvertierung in Numpy-Daten verarbeiten.
  2. "Keras" + "TensorFlow" Backend (von Python 2), in dem Numpy-Daten gelesen und klassifiziert werden.

(Programmierumgebung: IPython-Notebook 4.0.4, Python 3.5.1, Numpy 1.10.4, Pillow 3.1.1, Python 2.7.11, Keras 0.3.0, Tensorflow 0.7.0)

Schneiden Sie das Schriftbild aus und speichern Sie die Gurke

Da ich wenig Erfahrung mit 2-Byte-Schriftarten und Schriftbildern hatte, nahm diese Vorverarbeitungsarbeit, einschließlich der Recherche, viel Zeit in Anspruch. Die Hauptarbeit wurde mit der Bildklassenbibliothek von Pillow (PIL Fork) erledigt.

Importieren Sie zunächst die Bibliothek und laden Sie die Schriftart.

import numpy as np
import matplotlib.pyplot as plt
from PIL import ImageFont, ImageDraw, Image
%matplotlib inline

font = './kitamiji222_ver101.ttf'
font = ImageFont.truetype(font, 36)

Erstellen Sie als Nächstes eine Instanz des erforderlichen Bildes und schreiben Sie den Text dort.

text = u'AIUEO'
siz = font.getsize(text)
img1 = Image.new('RGB', siz, (255, 255, 255))
draw = ImageDraw.Draw(img1)
orig = (0, 0)
draw.text(orig, text, (0, 0, 0), font=font)

Zeigen Sie dies an und bestätigen Sie.

plt.imshow(img1)
plt.xticks([])
plt.yticks([])
plt.show()

a_gyo_RGB.PNG

Da die Schrift keine Farbinformationen benötigt, ist sie grau skaliert. Darüber hinaus wird es in eine Numpy-Matrix umgewandelt.

images = []
siz = (36, 36)
for hira_ch in hiralist:
    img_ch = Image.new('RGB', siz, (255, 255, 255))
    draw = ImageDraw.Draw(img_ch)
    orig = (0, 0)
    draw.text(orig, hira_ch, (0, 0, 0), font=font)
    img_ch_g = img_ch.convert('L')
    images.append(img_ch_g)

def PIL2npmat(img):
    return np.array(img.getdata(), np.uint8).reshape(img.size[1], img.size[0])

imgmats = [PIL2npmat(img) for img in images]

Speichern Sie es schließlich in einer Datei im Pickle-Format.

import pickle

mydata = [imgmats, codelist]
filename = 'kitamiji222.pkl'
outputfp = open(filename, 'wb')
pickle.dump(mydata, outputfp, protocol=2)
outputfp.close()

In der obigen Liste ist mydata das Python-Objekt, das Sie speichern möchten. Dieses Mal besteht die Prozedur darin, das Pickle in der Python3-Umgebung zu speichern und in die Python2-Umgebung zu laden. Um jedoch die Kompatibilität der Pickle-Datei zu gewährleisten, wird in "pickle.dump ()" protocol = 2 angegeben. ..

Test mit MLP-Modell (Multi-Layer Perceptron)

Wie oben erwähnt, wurde das Deep Learning Framework "Keras" verwendet, das Netzwerkmodell wurde jedoch unter Bezugnahme auf diesen Beispielcode "mnist_mlp.py" wie folgt definiert.

    trXshape = trainX[0].shape
    nclass = trainY.shape[1]
    hidden_units = 800
    
    model = Sequential()                                    #Sequentielle Modellinstanziierung
    model.add(Dense(hidden_units, input_shape=trXshape))    #Definition der verborgenen Schicht
    model.add(Activation('relu'))
    model.add(Dropout(0.3))
    model.add(Dense(hidden_units))                          #Definition der verborgenen Schicht
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(nclass))                                #Definition der Ausgabeebene
    model.add(Activation('softmax'))

    optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08) #Optimierungsdefinition
    model.compile(loss='categorical_crossentropy', optimizer=optimizer) #Kosten auswählen und Modell kompilieren

Da diesmal fünf Arten von Vokalen klassifiziert sind, enthält der Etikettendatenzug Informationen, die ['a', 'i', 'u', 'e', 'o'] entsprechen und aus dem zuvor hinzugefügten Schriftcode berechnet wurden. Ist enthalten. (Daher ist nclass = 5.)

Das Modell verwendet den sequentiellen Typ von Keras und wird in der Reihenfolge von der Eingabeseite zur Ausgabeseite definiert. Von der Eingabeseite wurden insgesamt 3 Schichten des MLP-Modells verwendet, verborgene Schicht 1 → verborgene Schicht 2 → Ausgangsschicht. Da das Schriftbild 36 x 36 (= 1296) ist, wird die Anzahl der verborgenen Ebeneneinheiten auf 800 festgelegt. Dropout () wird zur Regularisierung verwendet. Adam () wurde als Optimierer für das Lernen verwendet.

In neueren Keras kann "Theano" oder "TensorFlow" als Backend ausgewählt werden, diesmal wurde jedoch "TensorFlow" verwendet. Sie können das Ende der Keras-Bank angeben, indem Sie eine Umgebungsvariable festlegen.

export KERAS_BACKEND=tensorflow

Zunächst wurde die erforderliche Anzahl von Trainingsdaten (Zugdaten) und Testdaten (Testdaten) zufällig aus "Hiragana" entnommen und berechnet. Der Berechnungsstatus, die Kosten und die Genauigkeit sind in der folgenden Abbildung dargestellt.

Fig. MLP model, Loss and Accuracy mlp_t_1.png

Nach Abschluss der vorgegebenen Anzahl von Epochen konvergiert der Verlust gegen 0 und die Genauigkeit gegen 1,0. Zusätzlich betrug die Genauigkeit bei der nachfolgenden Klassifizierung unter Verwendung von Testdaten fast 1,0 (100%). Obwohl es zufällig ausgewählt wurde, gibt es keinen Unterschied in der Genauigkeit zwischen Zug und Test, da Zugdaten und Testdaten aus demselben Satz und derselben Population stammen.

Testen Sie "Katakana" mit dem MLP-Modell

Es ist nicht interessant, nur zu lernen, deshalb habe ich beschlossen, die Testdaten getrennt von den Trainingsdaten vorzubereiten. Glücklicherweise waren Hiragana und Katakana auf "Kitamiji 222" vorbereitet, und so entschied ich mich, einen Satz Hiragana als Trainingsdaten und einen Satz Katakana als Testdaten zu verwenden.

Vergleichen wir jedes Bild. ** Abb. Hiragana, von Linie zu Linie ** hira_20ch.PNG

** Abb. Katakana, von Linie A bis Linie ** kata_20ch.PNG

Es wird beobachtet, dass die Charaktere mit dem gleichen Klang in Hiragana und Katakana in ihrer Form ziemlich ähnlich sind. Es wurde festgestellt, dass der Unterschied zwischen Hiragana und Katakana dadurch ausgedrückt wird, ob der Mund "geschlossen" oder "offen" ist.

Daher wurden Zugdaten und Testdaten getrennt erstellt und die Berechnung durchgeführt.

Fig. MLP model, Loss and Accuracy mlp1.png

Fig. MLP model, Validation Loss and Validation Accuracy mlp2.png

Die Situation beim Lernen mit Hiragana (Zugdaten) ist fast dieselbe wie in der vorherigen Abbildung. Bei Validierungsverlust und -genauigkeit mit Katakana (Testdaten) nimmt der Verlust ab und die Genauigkeit nimmt wie beabsichtigt zu. Die endgültige Genauigkeit betrug 75%.

Ich habe die Berechnungsparameter geändert, um die Genauigkeit zu verbessern, aber der effektivste ist der Dropout-Wert. Durch Anpassen des Konformitätsgrades von Hiragana an das Emblem kann die Genauigkeit der Katakana-Klassifizierung verbessert werden. Was ich im Lehrbuch gelernt hatte, konnte ich in Form der Gesichtsbuchstaben erkennen. (Übrigens sind die guten Ergebnisse verschiedener Versuche in der obigen Liste aufgeführt, und die Abbrecherquote in der ersten Stufe beträgt 0,3 und die Abbrecherquote in der zweiten Stufe beträgt 0,5.

Getestet mit CNN (Convolitional Neural Network)

Ich habe das CNN-Modell (Convolutional Neural Network) für eine bessere Genauigkeit ausprobiert. Das Schöne an übergeordneten Klassenbibliotheken wie Keras ist, dass Sie das Modell mit wenigen Codeänderungen problemlos ändern können. Die Hauptteile des Codes sind unten gezeigt.

    nb_classes = trainY.shape[1]
    img_rows, img_cols = 36, 36     # image dimensions
    trainX = trainX.reshape(trainX.shape[0], 1, img_rows, img_cols)
    testX = testX.reshape(testX.shape[0], 1, img_rows, img_cols)
    nb_filters = 32                 # convolutional filters to use
    nb_pool = 2                     # size of pooling area for max pooling
    nb_conv = 3                     # convolution kernel size
    
    model = Sequential()                                     #Sequentielle Modellinstanziierung
    model.add(Convolution2D(nb_filters, nb_conv, nb_conv,    #Definition der Faltungsschicht
                        border_mode='valid',
                        input_shape=(1, img_rows, img_cols)))
    model.add(Activation('relu'))
    model.add(Convolution2D(nb_filters, nb_conv, nb_conv))   #Definition der Faltungsschicht
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool)))    #Definition der Pooling-Schicht
    model.add(Dropout(0.3))

    model.add(Flatten())
    model.add(Dense(128))                                    #Definition der vollständigen Bindungsschicht
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(nb_classes))                             #Definition der Ausgabeebene
    model.add(Activation('softmax'))

    optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)  #Optimierungsdefinition
    model.compile(loss='categorical_crossentropy', optimizer=optimizer)  #Kosten auswählen und Modell kompilieren

Von der Eingangsseite hat es eine fünfschichtige Struktur aus Faltungsschicht 1 → Faltungsschicht 2 → Pooling-Schicht → vollständig verbundener Schicht → Ausgangsschicht. (Wie Sie sich vorstellen können, folgt diese Ebenenstruktur dem Beispiel mnist_cnn.py.) Außerdem verwendet der Optimierer Adam wie zuvor.

Das Berechnungsergebnis ist wie folgt.

Fig. CNN model, Loss and Accuracy cnn1.png

Fig. CNN model, Validation Loss and Validation Accuracy cnn2.png

Wie beabsichtigt hat sich die Klassifizierungsgenauigkeit verbessert. Die endgültige Klassifizierungsgenauigkeit der Testdaten (Katakana) betrug 89%. Ich habe mein Bestes versucht, indem ich die Parameter angepasst habe, aber ich konnte es nicht auf das 90% -Niveau bringen. (Ich habe hauptsächlich die Abbrecherquote überprüft.)

Verglichen mit der 98 .. 99% Genauigkeit der handschriftlichen Nummernklassifizierungsaufgabe "MNIST" sind 89% etwas enttäuschend, aber die Stichprobengröße des Datensatzes unterscheidet sich zwischen MNIST und diesmal entscheidend. (In diesem Fall erfolgt die Abtastung nach dem Zufallsprinzip, die Typen sind jedoch auf den Schriftsatz beschränkt.) Um die Genauigkeit dieser Piktogrammklassifizierung weiter zu verbessern, verarbeiten Sie das Schriftbild (Verformung, Rauschaddition). Es ist schwierig, die Anzahl der Datenproben zu erhöhen. (Alternativ kann es etwas effektiv sein, die Regularisierungsmethode zu ändern.)

Abschließend möchte ich Herrn Kitamichi für die Veröffentlichung eines interessanten Themas des maschinellen Lernens danken. (Ich weiß, dass ich die Schrift nicht mit Blick auf maschinelles Lernen erstellt habe, aber ich konnte sie spielen !!!)

Referenzen (Website)

-Cat Piktogramm Schriftart "Kitamiji 222" produziert vom Schöpfer des 4-Frame-Cartoons "Pu-Neko" http://www.forest.impress.co.jp/docs/review/20160303_746474.html

Recommended Posts

Versuchen Sie, Piktogramm-Schriftarten mit Keras zu klassifizieren
Ich habe versucht, Keras in TFv1.1 zu integrieren
[Keras] Persönliches Memo zum Klassifizieren von Bildern nach Ordner [Python]
Klassifizieren Sie Mnist-Zahlen nach Keras, ohne dass der Lehrer etwas lernt [Auto Encoder Edition]
Erstellen Sie mit OpenCV eine Funktion zum Beschreiben japanischer Schriftarten
Klassifizieren Sie Anime-Gesichter durch Fortsetzung / Deep Learning mit Keras
Ich habe versucht, Grad-CAM mit Keras und Tensorflow zu implementieren
Konvertieren Sie 202003 bis 2020-03 mit Pandas
CIFAR-10-Tutorial mit Keras
Multivariates LSTM mit Keras
[TensorFlow 2 / Keras] Ausführen des Lernens mit CTC Loss in Keras
Ich habe versucht, MNIST nach GNN zu klassifizieren (mit PyTorch-Geometrie).
Für Anfänger, wie man mit häufigen Fehlern in Keras umgeht