Cet article est le 15e jour du calendrier de l'avent de Fujitsu Systems Web Technology. (Promesse) Le contenu de cet article est ma propre opinion et ne représente pas l'organisation à laquelle j'appartiens.
Dans cet article, ** en utilisant scikit-learn, la bibliothèque d'apprentissage automatique de Python Ceci est un résumé de la procédure et des résultats lorsque j'ai essayé la reconnaissance de caractères manuscrits des caractères runiques **. Alors que les pionniers de ce calendrier de l'Avent ont publié d'excellentes fonctionnalités et un savoir-faire qui semblent très utiles dans le travail réel, Je fais juste quelque chose qui est juste amusant pour moi, et je ne peux pas m'en empêcher. .. J'espère que vous pourrez y jeter un coup d'œil.
De plus, puisque l'auteur de cet article est un débutant en apprentissage automatique, il se peut qu'il y ait plus de contenu maintenant. Aussi pour ceux qui vont toucher python, scikit-learn Je ferai de mon mieux pour fournir des informations raisonnables. Je vous remercie.
Je n'y touche pas du tout dans mon travail quotidien, mais je m'intéresse à l'apprentissage automatique et je veux apprendre les bases de l'apprentissage et du mouvement. J'ai touché scikit-learn. J'aurais pu essayer d'utiliser l'ensemble de données de la bibliothèque, mais Je veux savoir "quel type de données puis-je préparer et que puis-je faire?" J'ai décidé de commencer par préparer les données.
** (De côté) ** Les personnages runiques sont plutôt cool, n'est-ce pas?
--Anaconda: un package qui inclut Python lui-même et les bibliothèques couramment utilisées. --scikit-learn: Une bibliothèque qui facilite l'utilisation des réseaux de neurones en Python. C'est open source. Cette fois, nous utiliserons un modèle appelé MLP Classifier qui effectue une «classification».
--E-cutter: logiciel gratuit pour la division d'image. Utilisé pour diviser des images de texte manuscrites.
Cette fois, nous nous concentrerons sur les "personnages de runes communs allemands (24 caractères)" parmi les personnages de runes.
Il ne semble pas y avoir de données pratiques telles que "données de caractères runiques pour l'apprentissage automatique", alors préparez votre propre image. Cette fois, je l'ai créé par la méthode suivante.
(1) Créez une image dans laquelle les caractères manuscrits sont alignés à la main à intervalles réguliers. (Ce sera pratique plus tard si le nom du fichier image est dessiné avec un caractère (exemple: "ᚠ. Png")) (2) Divisez l'image en parties égales avec E-cutter (logiciel gratuit). L'image divisée a été enregistrée dans le dossier spécifié avec "[nom du fichier d'origine] _ [numéro de branche] .png ", ce qui était très pratique. Une fois, j'ai créé 18 données d'image pour chaque type de personnage runique.
De là, nous traiterons en Python. Commencez par charger l'image.
import cv2 #Bibliothèque pour la conversion d'images
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import os, glob
#Tableau pour stocker les données d'image
X = []
#Caractères correspondant aux données d'image(répondre)Tableau à stocker
Y = []
#Fichier de répertoire de données d'entraînement
dir = "[Répertoire de stockage des données d'image]"
files = glob.glob(dir + "\\*.png ")
#Taille verticale et horizontale de l'image(pixel)
image_size = 50
#Lisez les fichiers du répertoire et ajoutez-les à la liste des données d'entraînement
for i, file in enumerate(files):
image = Image.open(file)
#Convertir en échelle de gris 8 bits
image = image.convert("L")
image = image.resize((image_size, image_size))
data = np.asarray(image).flatten()
X.append(data)
moji = file.split("\\")[-1].split("_")[0]
Y.append(moji)
X = np.array(X)
Y = np.array(Y)
Affichez l'image chargée.
#Visualisez les premières données
showimage = np.reshape(X[0], (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.show()
Il peut être lu comme des données de taille 50 * 50.
Le nombre de données est assez petit, mais apprenons et classons avec ces données (24 (caractères) * 18 (feuilles)) une fois!
#Divisez les données pour la formation et les tests
x_train, x_test, y_train, y_test = model_selection.train_test_split(X, Y, test_size=0.1, random_state=0)
#Apprentissage
clf = MLPClassifier(hidden_layer_sizes=(200,))
clf.fit(x_train, y_train)
#Catégoriser les données de test
y_pred = clf.predict(x_test)
#Voir les résultats
print("---Réponse supposée---")
print(y_test)
print("---La réponse donnée par le modèle---")
print(y_pred)
print("---Taux de réponse correct---")
accuracy_score(y_test, y_pred)
** Le pourcentage de bonnes réponses est très faible ...! !! (7,1%) ouz **
La plupart d'entre eux sont classés comme "ᚱ", et les autres caractères jugés sont également incorrects ... Cependant, ceux classés autres que "ᚱ" semblent être classés comme des personnages de formes similaires parmi les caractères runiques. Je suis un peu heureux d'avoir un aperçu du germe d'intelligence (même si j'ai fait une erreur après tout).
Il semble que les données d'apprentissage soient encore insuffisantes, mais il est difficile d'ajouter plus de données de caractères manuscrites. Essayez l'augmentation des données.
Préparé [Type de caractère] * 18 images ne suffisent pas pour l'apprentissage, donc Convertissez les données pour augmenter la quantité de données.
L'article suivant a été très utile pour l'augmentation des données. https://products.sint.co.jp/aisia/blog/vol1-7#toc-3
Il semble qu'il existe des méthodes telles que «augmenter le bruit», «inverser», «déplacer» et «transformer». Cette fois, nous y effectuerons "transformation" et "rotation".
#Transformez l'image
for i, file in enumerate(files):
image = Image.open(file)
image = image.resize((image_size, image_size))
image = image.convert("L")
moji = file.split("\\")[-1].split("_")[0]
#Inverser les bits de données dans un tableau
image_array = cv2.bitwise_not(np.array(image))
##Transformation ①
#Créer une carte de transformation de l'image
pts1 = np.float32([[0,0],[0,100],[100,100],[100,0]])
pts2 = np.float32([[0,0],[0, 98],[102,102],[100,0]])
#Transformation d'image
M = cv2.getPerspectiveTransform(pts1,pts2)
dst1 = cv2.warpPerspective(image_array,M,(50, 50))
X.append(dst1.flatten())
Y.append(moji)
##Transformation ②
#Créer une carte de transformation de l'image
pts2 = np.float32([[0,0],[0, 102],[98, 98],[100,0]])
#Transformation d'image
M = cv2.getPerspectiveTransform(pts1,pts2)
dst2 = cv2.warpPerspective(image_array,M,(50, 50))
X.append(dst2.flatten())
Y.append(moji)
#Afficher les dernières données
showimage = np.reshape(image_array, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
J'ai pu générer une image légèrement déformée par rapport à l'image d'origine. Générez deux images déformées pour chaque image originale et ajoutez-les aux données d'entraînement.
Pour augmenter davantage les données, créez une image avec l'image d'origine tournée de 15 degrés et ajoutez-la.
#Faire pivoter l'image
for i, file in enumerate(files):
image = Image.open(file)
image = image.resize((image_size, image_size))
image = image.convert("L")
moji = file.split("\\")[-1].split("_")[0]
#Inverser les bits de données dans un tableau
image = cv2.bitwise_not(np.array(image))
#1. 1. Rotation de 15 degrés dans le sens des aiguilles d'une montre
#Spécifiez l'angle de rotation
angle = -15.0
#Spécifiez l'échelle
scale = 1.0
#Utilisez la fonction getRotationMatrix2D
trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
#Conversion d'affine
image1 = cv2.warpAffine(image, trans, (50, 50))
X.append(image1.flatten())
Y.append(moji)
#2. Rotation de 15 degrés dans le sens antihoraire
#Spécifiez l'angle de rotation
angle = 15.0
#Spécifiez l'échelle
scale = 1.0
#Utilisez la fonction getRotationMatrix2D(Arguments: position centrale, angle de rotation, échelle)
trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
#Conversion d'affine
image2 = cv2.warpAffine(image, trans, (50, 50))
X.append(image2.flatten())
Y.append(moji)
#Afficher les dernières données
showimage = np.reshape(image, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(image1),plt.title('Output')
plt.show()
showimage = np.reshape(image, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(image2),plt.title('Output')
plt.show()
L'image d'origine a été tournée de 15 degrés vers la gauche et la droite pour générer chaque image. Cette image est également ajoutée aux données d'entraînement.
Avec cela, le nombre de données pour la formation est 5 fois supérieur à l'original (original, transformation ①, transformation ②, rotation droite, rotation gauche).
Reconnaissons (classons) les images pour apprendre et tester à nouveau!
** La précision s'est améliorée ...! (86,9%) **
Le résultat était quelque chose comme "J'ai augmenté les données et la précision de l'analyse s'est améliorée! Je l'ai fait!" Après tout, je me demandais à quel point chacune des images déformées était efficace, alors En gros, j'ai essayé de vérifier le taux de réponse correct en modifiant la répartition des données à former. J'ai pu confirmer que le taux de réponse correct était suffisamment élevé pour donner des variations à l'image.
Je voudrais continuer à vérifier si d'autres méthodes ("rognage", "bruit" ...) amélioreront encore la précision. De plus, cette fois, je voudrais vérifier le modèle dans lequel le nombre de nœuds de couche cachés dans le réseau neuronal a été modifié, qui a été fixé à 200.
Merci pour la lecture!
Recommended Posts