Dieser Artikel ist der 15. Tagesartikel des Fujitsu Systems Web Technology Adventskalenders. (Versprechen) Der Inhalt dieses Artikels ist meine eigene Meinung und repräsentiert nicht die Organisation, zu der ich gehöre.
In diesem Artikel ** mit scikit-learn, der maschinellen Lernbibliothek von Python Dies ist eine Zusammenfassung des Verfahrens und der Ergebnisse, als ich versuchte, Runenzeichen mit handschriftlichen Zeichen zu erkennen **. Während die Pioniere dieses Adventskalenders großartige Funktionen und Know-how veröffentlicht haben, die für die eigentliche Arbeit recht nützlich zu sein scheinen, Ich mache einfach etwas, das mir einfach Spaß macht, und ich kann nichts dagegen tun. .. Ich hoffe, Sie können einen kurzen Blick darauf werfen.
Da der Autor dieses Artikels ein Anfänger im maschinellen Lernen ist, gibt es jetzt möglicherweise mehr Inhalte. Auch für diejenigen, die Python berühren wollen, Scikit-Learn Ich werde mein Bestes tun, um angemessene Informationen bereitzustellen. Vielen Dank.
Ich fasse es in meiner täglichen Arbeit überhaupt nicht an, aber ich interessiere mich für maschinelles Lernen und möchte die Grundlagen des Lernens und der Bewegung lernen. Ich berührte Scikit-Learn. Ich hätte versuchen können, den Datensatz der Bibliothek zu verwenden, aber Ich möchte wissen, "welche Art von Daten kann ich vorbereiten und was kann ich tun?" Ich beschloss, zunächst die Daten vorzubereiten.
** (beiseite) ** Runencharaktere sind irgendwie cool, nicht wahr?
--Anaconda: Ein Paket, das Python selbst und häufig verwendete Bibliotheken enthält. --scikit-learn: Eine Bibliothek, die die Verwendung neuronaler Netze in Python vereinfacht. Es ist Open Source. Dieses Mal werden wir ein Modell namens MLP Classifier verwenden, das eine "Klassifizierung" durchführt.
Dieses Mal konzentrieren wir uns auf "Deutsche gemeinsame Runenzeichen (24 Zeichen)" unter den Runenzeichen.
Es scheint keine geeigneten Daten wie "Runenzeichendaten für maschinelles Lernen" zu geben. Bereiten Sie also Ihr eigenes Bild vor. Dieses Mal habe ich es mit der folgenden Methode erstellt.
(1) Erstellen Sie ein Bild, in dem handgeschriebene Zeichen in regelmäßigen Abständen von Hand aneinandergereiht werden. (Es ist später praktisch, wenn der Name der Bilddatei mit einem Zeichen gezeichnet wird (Beispiel: "ᚠ. Png")) (2) Teilen Sie das Bild mit dem E-Cutter (freie Software) in gleiche Teile. Das geteilte Bild wurde im angegebenen Ordner mit "[ursprünglicher Dateiname] _ [Zweigstellennummer] .png " gespeichert, was sehr praktisch war. Einmal habe ich 18 Bilddaten für jede Art von Runenzeichen erstellt.
Von hier aus werden wir in Python verarbeiten. Laden Sie zuerst das Bild.
import cv2 #Bibliothek zur Bildkonvertierung
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import os, glob
#Array zum Speichern von Bilddaten
X = []
#Zeichen, die Bilddaten entsprechen(Antworten)Array zum Speichern
Y = []
#Trainingsdatenverzeichnisdatei
dir = "[Bilddatenspeicherverzeichnis]"
files = glob.glob(dir + "\\*.png ")
#Vertikale und horizontale Größe des Bildes(Pixel)
image_size = 50
#Lesen Sie die Dateien im Verzeichnis und fügen Sie sie der Liste der Trainingsdaten hinzu
for i, file in enumerate(files):
image = Image.open(file)
#In 8-Bit-Graustufen konvertieren
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)
Lassen Sie uns das geladene Bild anzeigen.
#Visualisieren Sie die ersten Daten
showimage = np.reshape(X[0], (50,50)) #Erstellen Sie ein 50x50-Doppelarray mit Umformung
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.show()
Es kann als Daten mit einer Größe von 50 * 50 gelesen werden.
Die Anzahl der Daten ist recht gering, aber lassen Sie uns diese Daten (24 (Zeichen) * 18 (Blätter)) einmal lernen und klassifizieren!
#Teilen Sie die Daten für Training und Test
x_train, x_test, y_train, y_test = model_selection.train_test_split(X, Y, test_size=0.1, random_state=0)
#Lernen
clf = MLPClassifier(hidden_layer_sizes=(200,))
clf.fit(x_train, y_train)
#Kategorisieren Sie Testdaten
y_pred = clf.predict(x_test)
#Ergebnisse anzeigen
print("---Angenommene Antwort---")
print(y_test)
print("---Die Antwort des Modells---")
print(y_pred)
print("---Richtige Antwortrate---")
accuracy_score(y_test, y_pred)
** Der Prozentsatz der richtigen Antworten ist sehr gering ...! !! (7,1%) orz **
Die meisten von ihnen sind als "ᚱ" klassifiziert, und die anderen beurteilten Zeichen sind ebenfalls falsch ... Andere als "ᚱ" klassifizierte scheinen jedoch als Zeichen mit ähnlichen Formen unter den Runenzeichen klassifiziert zu sein. Ich bin ein wenig froh, einen Blick auf den Spross der Intelligenz zu werfen (obwohl ich doch einen Fehler gemacht habe).
Es scheint, dass die Trainingsdaten immer noch nicht ausreichen, aber es ist mühsam, mehr handschriftliche Zeichendaten hinzuzufügen. Versuchen Sie die Datenerweiterung.
Vorbereitet [Zeichentyp] * 18 Bilder reichen also nicht zum Lernen aus Konvertieren Sie Daten, um die Datenmenge zu erhöhen.
Der folgende Artikel war sehr hilfreich für die Datenerweiterung. https://products.sint.co.jp/aisia/blog/vol1-7#toc-3
Es scheint, dass es Methoden wie "Rauschen erhöhen", "Umkehren", "Verschieben" und "Transformieren" gibt. Dieses Mal werden wir darin "Transformation" und "Rotation" durchführen.
#Transformiere das Bild
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]
#Invertieren Sie die Datenbits in ein Array
image_array = cv2.bitwise_not(np.array(image))
##Transformation ①
#Transformationskarte des Bildes erstellen
pts1 = np.float32([[0,0],[0,100],[100,100],[100,0]])
pts2 = np.float32([[0,0],[0, 98],[102,102],[100,0]])
#Bildtransformation
M = cv2.getPerspectiveTransform(pts1,pts2)
dst1 = cv2.warpPerspective(image_array,M,(50, 50))
X.append(dst1.flatten())
Y.append(moji)
##Transformation ②
#Transformationskarte des Bildes erstellen
pts2 = np.float32([[0,0],[0, 102],[98, 98],[100,0]])
#Bildtransformation
M = cv2.getPerspectiveTransform(pts1,pts2)
dst2 = cv2.warpPerspective(image_array,M,(50, 50))
X.append(dst2.flatten())
Y.append(moji)
#Zeigen Sie die letzten Daten an
showimage = np.reshape(image_array, (50,50)) #Erstellen Sie ein 50x50-Doppelarray mit Umformung
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
Ich konnte ein Bild erzeugen, das im Vergleich zum Originalbild leicht deformiert war. Generieren Sie zwei deformierte Bilder für jedes Originalbild und fügen Sie sie den Trainingsdaten hinzu.
Um die Daten weiter zu erhöhen, erstellen Sie ein Bild mit dem um 15 Grad gedrehten Originalbild und fügen Sie es hinzu.
#Drehen Sie das Bild
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]
#Invertieren Sie die Datenbits in ein Array
image = cv2.bitwise_not(np.array(image))
#1. 1. 15 Grad im Uhrzeigersinn drehen
#Geben Sie den Drehwinkel an
angle = -15.0
#Maßstab angeben
scale = 1.0
#Verwenden Sie die Funktion getRotationMatrix2D
trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
#Affin-Konvertierung
image1 = cv2.warpAffine(image, trans, (50, 50))
X.append(image1.flatten())
Y.append(moji)
#2. 15 Grad gegen den Uhrzeigersinn drehen
#Geben Sie den Drehwinkel an
angle = 15.0
#Maßstab angeben
scale = 1.0
#Verwenden Sie die Funktion getRotationMatrix2D(Argumente: Mittelstellung, Drehwinkel, Maßstab)
trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
#Affin-Konvertierung
image2 = cv2.warpAffine(image, trans, (50, 50))
X.append(image2.flatten())
Y.append(moji)
#Zeigen Sie die letzten Daten an
showimage = np.reshape(image, (50,50)) #Erstellen Sie ein 50x50-Doppelarray mit Umformung
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)) #Erstellen Sie ein 50x50-Doppelarray mit Umformung
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(image2),plt.title('Output')
plt.show()
Das Originalbild wurde um 15 Grad nach links und rechts gedreht, um jedes Bild zu erzeugen. Dieses Bild wird auch zu den Trainingsdaten hinzugefügt.
Damit beträgt die Anzahl der zu trainierenden Daten das Fünffache des Originals (Original, Transformation ①, Transformation ②, Rechtsdrehung, Linksdrehung).
Versuchen wir erneut, Bilder zum Lernen und Testen zu erkennen (zu klassifizieren)!
** Genauigkeit hat sich verbessert ...! (86,9%) **
Das Ergebnis war so etwas wie "Ich habe die Daten erhöht und die Analysegenauigkeit verbessert! Ich habe es geschafft!" Immerhin habe ich mich gefragt, wie effektiv jedes der deformierten Bilder ist Grob gesagt habe ich versucht, die richtige Antwortrate zu überprüfen, indem ich die Aufschlüsselung der zu trainierenden Daten geändert habe. Ich konnte bestätigen, dass die richtige Antwortrate hoch genug war, um das Bild zu variieren.
Ich möchte weiterhin überprüfen, ob andere Methoden ("Trimmen", "Rauschen" ...) die Genauigkeit weiter verbessern. Auch dieses Mal möchte ich das Muster überprüfen, in dem die Anzahl der Knoten mit versteckten Schichten im neuronalen Netzwerk geändert wurde, das auf 200 festgelegt wurde.
Danke fürs Lesen!
Recommended Posts