L'artiste manga Masayuki Kitamichi a produit et publié la police "Kitamiji 222" pour commémorer "Cat Day" le 22 février.
http://kitamichi.sub.jp/Sites/iblog/C513573485/E937677024/ (Article d'introduction: http://www.forest.impress.co.jp/docs/review/20160303_746474.html)
Tout d'abord, vérifiez la licence.
◆ À propos de l'utilisation
"Kitamiji 222" est un logiciel gratuit. S'il n'est pas destiné à un usage commercial, vous pouvez l'utiliser librement sans aucune restriction. Cependant, veuillez vous abstenir de vendre, redistribuer ou traiter le "corps du fichier de police".
Le copyright de "Kitamiji 222" appartient à Masayuki Kitado. Nous ne sommes pas responsables de toute machine ou d'autres problèmes causés par l'utilisation de polices.
(Cette fois, j'ai découpé l'image de la police et l'ai utilisée comme données d'apprentissage automatique, mais je pense qu'elle ne correspond pas au traitement du "corps du fichier de police". → M. Kitamichi a accepté d'utiliser cette police.)
Par exemple, "aiueo" et "kakikukeko" sont affichés comme suit. ** AIUEO **
** Kakikukeko **
De cette façon, la différence de voyelles est exprimée par la direction du visage du chat, et la différence de consonnes est exprimée par la différence de motif de poils. Intuitivement, j'ai senti que la reconnaissance de la voyelle "aiueo" pouvait se faire relativement facilement avec un classificateur composé d'un réseau neuronal, j'ai donc essayé ceci. ("A" et "e" ("ka" et "ke") se ressemblent un peu, mais cela semble un peu difficile à classer.)
Puisque «Kitamiji 222» est fourni dans la police TrueType, le travail a été effectué dans le flux suivant.
(Environnement de programmation: IPython-notebook 4.0.4, python 3.5.1, numpy 1.10.4, oreiller 3.1.1, python 2.7.11, keras 0.3.0, tensorflow 0.7.0)
Comme je n'avais que peu d'expérience avec les polices 2 octets et les images de polices, ce travail de prétraitement, y compris la recherche, a pris un temps considérable. Le travail principal a été réalisé avec la bibliothèque de classes Image de Pillow (PIL Fork).
Tout d'abord, importez la bibliothèque et chargez la police.
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)
Ensuite, créez une instance de l'image requise et écrivez-y le texte.
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)
Affichez-le et confirmez.
plt.imshow(img1)
plt.xticks([])
plt.yticks([])
plt.show()
Étant donné que la police n'a pas besoin d'informations de couleur, elle est en niveaux de gris. De plus, il est converti en une matrice Numpy.
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]
Enfin, enregistrez-le dans un fichier au format pickle.
import pickle
mydata = [imgmats, codelist]
filename = 'kitamiji222.pkl'
outputfp = open(filename, 'wb')
pickle.dump(mydata, outputfp, protocol=2)
outputfp.close()
Dans la liste ci-dessus, mydata est l'objet python que vous souhaitez enregistrer. Cette fois, la procédure est de sauvegarder le pickle dans l'environnement python3 et de le charger dans l'environnement python2, mais afin de maintenir la compatibilité du fichier pickle, protocol = 2
est spécifié dans pickle.dump ()
. ..
Comme mentionné ci-dessus, le Deep Learning Framework «Keras» a été utilisé, mais le modèle de réseau a été défini comme suit en référence à cet exemple de code «mnist_mlp.py».
trXshape = trainX[0].shape
nclass = trainY.shape[1]
hidden_units = 800
model = Sequential() #Instanciation séquentielle du modèle
model.add(Dense(hidden_units, input_shape=trXshape)) #Définition de la couche cachée
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Dense(hidden_units)) #Définition de la couche cachée
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nclass)) #Définition de la couche de sortie
model.add(Activation('softmax'))
optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08) #Définition de l'optimiseur
model.compile(loss='categorical_crossentropy', optimizer=optimizer) #Sélectionnez le coût et compilez le modèle
Puisqu'il existe cinq types de voyelles classées cette fois, les données d'étiquette trainY contiennent des informations correspondant à ['a', 'i', 'u', 'e', 'o'] calculées à partir du code de police ajouté à l'avance. Est inclus. (Par conséquent, nclass = 5.)
Le modèle utilise le type séquentiel de Keras et est défini dans l'ordre du côté entrée au côté sortie. Du côté de l'entrée, un total de trois modèles MLP, couche cachée 1 → couche cachée 2 → couche de sortie, ont été utilisés. Étant donné que l'image de la police est 36x36 (= 1296), le nombre d'unités de calque masquées est défini sur 800. Dropout () est utilisé pour la régularisation. Adam () a été utilisé comme optimiseur pour l'apprentissage.
Dans Keras récent, "Theano" ou "TensorFlow" peut être sélectionné comme backend, mais cette fois "TensorFlow" a été utilisé. Vous pouvez spécifier la fin de la banque Keras en définissant une variable d'environnement.
export KERAS_BACKEND=tensorflow
Tout d'abord, le nombre requis de données d'entraînement (données de train) et de données de test (données de test) a été échantillonné au hasard à partir de "Hiragana" et calculé. L'état, le coût et la précision du calcul sont indiqués dans la figure ci-dessous.
Fig. MLP model, Loss and Accuracy
Après avoir terminé le nombre d'époques prédéterminé, la perte converge vers près de 0 et la précision converge vers près de 1,0. De plus, la précision était de près de 1,0 (100%) dans la classification ultérieure utilisant les données de test. Même s'il a été échantillonné au hasard, il n'y a pas de différence de précision entre Train et Test, car les données de train et les données de test sont tirées du même ensemble et de la même population.
Il n'est pas intéressant d'apprendre simplement, j'ai donc décidé de préparer les données de test séparément des données d'entraînement. Heureusement, les hiragana et katakana ont été préparés pour "Kitamiji 222", nous avons donc décidé d'utiliser un ensemble de hiragana comme données d'entraînement et un ensemble de katakana comme données de test.
Comparons chaque image. ** Fig. Hiragana, de ligne en ligne **
** Fig. Katakana, de la ligne A à la ligne **
On observe que les personnages avec le même son en hiragana et en katakana sont de forme assez similaire. Il a été constaté que la différence entre hiragana et katakana s'exprime par le fait que la bouche est «fermée» ou «ouverte».
Par conséquent, les données de train et les données de test ont été préparées séparément et le calcul a été effectué.
Fig. MLP model, Loss and Accuracy
Fig. MLP model, Validation Loss and Validation Accuracy
La situation d'apprentissage en utilisant Hiragana (données de train) est presque la même que la figure précédente. En ce qui concerne la perte de validation et la précision en utilisant Katakana (données de test), la perte diminue et la précision augmente comme prévu. La précision finale était de 75%.
J'ai changé les paramètres de calcul pour améliorer la précision, mais le plus efficace est la valeur de décrochage. En ajustant le degré de conformité du hiragana à l'emblème, la précision de la classification des katakana peut être améliorée. J'ai pu réaliser ce que j'ai appris dans le manuel sous la forme des lettres faciales. (À propos, les bons résultats de divers essais sont indiqués dans la liste ci-dessus, et le taux d'abandon dans la première étape est de 0,3 et le taux d'abandon dans la deuxième étape est de 0,5.
J'ai essayé le modèle CNN (Convolutional Neural Network) pour une meilleure précision. L'avantage des bibliothèques de classes de haut niveau comme Keras est que vous pouvez facilement modifier le modèle avec quelques modifications de code. Les principales parties du code sont présentées ci-dessous.
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() #Instanciation séquentielle du modèle
model.add(Convolution2D(nb_filters, nb_conv, nb_conv, #Définition de la couche convolutive
border_mode='valid',
input_shape=(1, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, nb_conv, nb_conv)) #Définition de la couche convolutive
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool))) #Définition de la couche de pooling
model.add(Dropout(0.3))
model.add(Flatten())
model.add(Dense(128)) #Définition de la couche de liaison complète
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes)) #Définition de la couche de sortie
model.add(Activation('softmax'))
optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08) #Définition de l'optimiseur
model.compile(loss='categorical_crossentropy', optimizer=optimizer) #Sélectionnez le coût et compilez le modèle
Du côté de l'entrée, il a une structure à cinq couches: couche de convolution 1 → couche de convolution 2 → couche de regroupement → couche entièrement connectée → couche de sortie. (Comme vous pouvez l'imaginer, cette structure de couche suit l'exemple mnist_cnn.py.) De plus, l'optimiseur utilise Adam comme auparavant.
Le résultat du calcul est le suivant.
Fig. CNN model, Loss and Accuracy
Fig. CNN model, Validation Loss and Validation Accuracy
Comme prévu, la précision de la classification s'est améliorée. La précision de classification finale des données de test (Katakana) était de 89%. J'ai fait de mon mieux en ajustant les paramètres, mais je ne pouvais pas l'obtenir au niveau de 90%. (J'ai vérifié principalement le taux d'abandon.)
Par rapport à la précision de 98 .. 99% de la tâche de classification des nombres manuscrits "MNIST", 89% est un peu décevant, mais le nombre d'échantillons de jeux de données est nettement différent entre MNIST et cette fois. (Dans ce cas, l'échantillonnage est effectué de manière aléatoire, mais les types sont limités au jeu de polices.) Pour améliorer encore la précision de cette classification de pictogrammes, traitez l'image de la police (déformation, ajout de bruit) Etc., il est nécessaire d'avoir du mal à augmenter le nombre d'échantillons de données. (Sinon, il peut être assez efficace de changer la méthode de régularisation.)
Enfin, je voudrais remercier M. Kitamichi pour avoir publié un sujet intéressant sur l'apprentissage automatique. (Je sais que je n'ai pas créé la police avec l'apprentissage automatique à l'esprit, mais j'ai pu la jouer !!!)
-Police de pictogramme de chat "Kitamiji 222" réalisée par le créateur du dessin animé à 4 images "Pu-Neko" http://www.forest.impress.co.jp/docs/review/20160303_746474.html
Recommended Posts