In den letzten Jahren hat das Gebiet der künstlichen Intelligenz bemerkenswerte Fortschritte gemacht. Ein Algorithmus, der als neuronales Netzwerk bezeichnet wird, wird im Allgemeinen verwendet, um Dinge durch künstliche Intelligenz zu erkennen und zu beurteilen. Dies ist ein Versuch, die Funktionsweise des menschlichen Gehirns nachzuahmen, da es automatisch aus einem technischen Ansatz lernt. Lassen Sie diesmal den Computer die handgeschriebenen Zahlen erkennen, damit der Mensch sie auf natürliche Weise erkennen kann.
Ein neuronales Netzwerk ist ein Lernmodell, das den Nerv des menschlichen Gehirns nachahmt. Durch die Durchführung einer großen Anzahl nichtlinearer Transformationen ist dies ein Ersatz, der aus gegebenen Daten sehr komplexe Ergebnisse liefern kann. Auf dem Gebiet der Bilderkennung kann gesagt werden, dass die Bilderkennung durch Anwenden eines Korrelationsprozesses, der als Schablonenanpassung bezeichnet wird, auf das neuronale Netz realisiert wird. (Obwohl es einige Missverständnisse geben kann, handelt es sich nur um einen Korrelationsprozess in Bezug auf die Faltung von Pixeln und die Helligkeit.)
Das diesmal zu erkennende Bild ist eine handschriftliche Nummer von MNIST.
Lassen Sie uns herunterladen. Da es sich nicht um Bilddaten handelt, können diese nach dem Herunterladen so verwendet werden, wie sie sind Konvertieren wir es in Bilddaten, indem wir auf die folgenden Dokumente auf der offiziellen Website verweisen.
TRAINING SET LABEL FILE (train-labels-idx1-ubyte):
[offset] [type] [value] [description] 0000 32 bit integer 0x00000801(2049) magic number (MSB first) 0004 32 bit integer 60000 number of items 0008 unsigned byte ?? label 0009 unsigned byte ?? label ........ xxxx unsigned byte ?? label The labels values are 0 to 9.
TRAINING SET IMAGE FILE (train-images-idx3-ubyte):
[offset] [type] [value] [description] 0000 32 bit integer 0x00000803(2051) magic number 0004 32 bit integer 60000 number of images 0008 32 bit integer 28 number of rows 0012 32 bit integer 28 number of columns 0016 unsigned byte ?? pixel 0017 unsigned byte ?? pixel ........ xxxx unsigned byte ?? pixel Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).
Sie können sehen, dass das Lehrersignal nach dem Versatz 8 und die Trainingsdaten nach dem Versatz 16 gespeichert werden. Wenn Sie es daher als Binärdatei öffnen und die Byte-Zeichenfolge für jeden Pixelwert (28 * 28) extrahieren, können Sie die Bilddatei abrufen. Durch ordnungsgemäße Binärisierung können Sie die folgenden Bilddaten handgeschriebener Zahlen für 60000-Daten erhalten. Wir werden diese Plus-Testdaten beim Training des neuronalen Netzes verwenden.
Das Modell des diesmal verwendeten neuronalen Netzes wird durch die folgenden Anforderungen definiert.
Es ist ein einfaches und extrem neuronales Netzwerk, aber ist es der Punkt, dass es zwei versteckte Schichten verwendet? Es gibt viele Dinge, die verbessert werden müssen, aber lassen Sie uns dies zunächst in die Praxis umsetzen.
Die Code-Implementierung ist unten dargestellt.
MultiLayerPerceptron_MNIST.py
# 1. Preprocess
import random
# 1.1. Make NeuralLetwork
# 1.1.1. Define Layers
n_hidden = 2
n_layer = n_hidden + 2
# 1.1.2. Define Units
n_unit_i = 7 * 7 + 1
n_unit_h = 20 # all
n_unit_o = 10
unit_i = [0 for u in range(n_unit_i)]
unit_h1 = [0 for u in range(n_unit_h)]
unit_h2 = [0 for u in range(n_unit_h)]
unit_o = [0 for u in range(n_unit_o)]
# 1.1.3. Initialize weight
w1 = [[random.uniform(-1, 1) for u_before in range(n_unit_i)] for u_after in range(n_unit_h)]
w2 = [[random.uniform(-1, 1) for u_before in range(n_unit_h)] for u_after in range(n_unit_h)]
w3 = [[random.uniform(-1, 1) for u_before in range(n_unit_h)] for u_after in range(n_unit_o)]
# 1.2. Define dataset
import mydatasets
n_data = 100
ipt = mydatasets.inputdata("digit")
res = ipt.load_data2(size=(7, 7), num=n_data)
train = res[0][0]
for k in train:
for n in k:
n.insert(0, 1)
def maketeach(kind):
buf = []
for o in range(n_unit_o):
if o == kind:
buf.append(1)
else:
buf.append(0)
return buf
# 1.3 Implement forward propagation
import math
# 1.3.1 Define activation fucntion
def sigmoid(z):
if z > 10: return 0.99999
elif z < -10: return 0.00001
else: return 1 / (1 + math.exp(-1 * z))
# 1.3.2 forward propagation
def forward(train_vec):
for i in range(n_unit_i):
unit_i[i] = train_vec[i]
unit_i[0] = 1
# 1.3.2.1 forward between input-hidden1
for h1 in range(n_unit_h):
buf = 0
for i in range(n_unit_i):
buf += unit_i[i] * w1[h1][i]
unit_h1[h1] = sigmoid(buf)
unit_h1[0] = 1
# 1.3.2.2 forward between hidden1-hidden2
for h2 in range(n_unit_h):
buf = 0
for h1 in range(n_unit_h):
buf += unit_h1[h1] * w2[h2][h1]
unit_h2[h2] = sigmoid(buf)
unit_h2[0] = 1
# 1.3.2.3 forward between hidden2-output
for o in range(n_unit_o):
buf = 0
for h2 in range(n_unit_h):
buf += unit_h2[h2] * w3[o][h2]
unit_o[o] = sigmoid(buf)
# 1.3.3 back propagation
alpha = 0.1
def backpropagation(teach_vec):
# 1.3.3.1 get cost
buf = 0
for o in range(n_unit_o):
buf += (teach_vec[o] - unit_o[o]) ** 2
cost = buf / 2
# 1.3.3.2 get grad between hidden2-output
for o in range(n_unit_o):
for h2 in range(n_unit_h):
delta = (unit_o[o] - teach_vec[o]) * unit_o[o] * (1 - unit_o[o]) * unit_h2[h2]
w3[o][h2] -= alpha * delta
# 1.3.3.3 get grad
for o in range(n_unit_o):
for h2 in range(n_unit_h):
for h1 in range(n_unit_h):
delta = ((unit_o[o] - teach_vec[o]) * unit_o[o] * (1 - unit_o[o])
* w3[o][h2] * unit_h2[h2] * (1 - unit_h2[h2]) * unit_h1[h1])
w2[h2][h1] -= alpha * delta
# 1.3.3.4 get grad
for o in range(n_unit_o):
for h2 in range(n_unit_h):
for h1 in range(n_unit_h):
for i in range(n_unit_i):
delta = ((unit_o[o] - teach_vec[o]) * unit_o[o] * (1 - unit_o[o])
* w3[o][h2] * unit_h2[h2] * (1 - unit_h2[h2])
* w2[h2][h1] * unit_h1[h1] * (1 -unit_h1[h1]) * unit_i[i])
w1[h1][i] -= alpha *delta
return cost
import matplotlib.pyplot as plt
plt_x = []
plt_y = []
n_epoch = 30
n_train = len(train)
n_kind = 10
n = 0
error_threshold = 0.001
print("Backpropagation training is started now.")
def training(n):
for e in range(n_epoch):
for d in range(n_data):
for k in range(n_kind):
try:
n += 1
forward(train[k][d])
c = backpropagation(maketeach(k))
plt_x.append(n)
plt_y.append(c)
if n % 100 == 0:
print("learn num: {0}".format(n))
if c < error_threshold and e > n_epoch // 2:
print("cost is least than error threshold. (n: {})".format(n))
return 1
except Exception as e:
print("n:{}, d:{}, k{}, Error:{}".format(n, d, k, e.args))
pass
return 0
def forecast(train_data, dim):
forward(train_data)
res = unit_o
n = 0
for r in res:
if r == max(res):
max_score = n
n += 1
print("max score : {}".format(max_score))
print("scores is below : ")
print(res)
import numpy as np
import cv2
mat = []
row = []
cnt = 0
n = 0
for t in range(1, len(train_data)):
row.append(train_data[t])
cnt += 1
n += 1
if cnt == 7:
#print("if statement is called at n:{}".format(n))
mat.append(row)
row = []
cnt = 0
cv2.imwrite('forecast_input.png', np.array(mat)*255)
return max_score
def validation(vaild_sets):
n_dim = 7
correct = 0
incorrect = 0
n_kind = 10
for d in range(n_data):
for k in range(n_kind):
if forecast(train[k][d], n_dim) == k:
correct += 1
else:
incorrect += 1
total = correct + incorrect
print("validation result:: correct answer is {} / {}".format(correct, total))
training(n)
plt.plot(plt_x, plt_y)
plt.xlim(0, 30000)
plt.ylim(0.0, 1.51)
plt.show()
valid = res[1][0]
for k in valid:
for n in k:
n.insert(0, 1)
validation(valid)
Unter Verwendung der Anzahl der Lernfehlergraphen wurden die folgenden Ergebnisse erhalten.
Zu Beginn kann das neuronale Netz nicht zwischen 0 (richtige Antwort) und 1 (falsche Antwort) unterscheiden und trifft eine halbfertige Beurteilung von 0,5. Wenn Sie lernen, können Sie immer mehr unterscheiden. Wenn das Ergebnis korrekt ist, können Sie ein Urteil nahe 0 fällen. Wenn das Ergebnis falsch ist, können Sie ein Urteil nahe 1 fällen.
Dies ist das Ergebnis der Verwendung von Sigmoid für die Ausgabeaktivierungsfunktion. Sigmoid bewirkt eine Normalisierung des Wertes im Bereich von 0 bis 1, was den Erfolg oder Misserfolg der Erkennung in Form einer Wahrscheinlichkeit anzeigt.
Als Ergebnis der Validierung betrug die Erkennungsrate handgeschriebener Zahlen 84,7%. Wenn Sie mit dem oben genannten primitiven Algorithmus ein solches Ergebnis erzielen können, können Sie sagen, dass es Ihnen vorerst gelungen ist, handgeschriebene Zahlen zu erkennen.
Ich wurde darauf hingewiesen, dass die Bedeutung des Ausführungsergebnisses schwer zu lesen ist, daher werde ich eine Erklärung hinzufügen.
Lassen Sie uns zunächst den Bereich der Ausführungsergebnisse verfeinern.
Die obige Abbildung zeigt die Fehlerrate bis zum Versuch 29970 ... 30000. Sie können die Periodizität in diesem Diagramm sehen. Die Periodizität für jeden Zifferntyp (0 ... 9), z. B. niedriger Fehler, wenn die Einerstelle 0 oder 1 ist, und hoher Fehler, wenn die Einerstelle 9 ist.
Diese Vibration ist auf den Lernalgorithmus zurückzuführen. In dem diesmal verwendeten Algorithmus wird Shioume, wie das Lernen von 1 nach dem Lernen von 0, dazu gebracht, jedes Mal die folgenden Arten von Zahlen zu lernen. Daher schwankt die Fehlerrate in Abhängigkeit von der Anzahl der Versuche stark. Es gibt keine direkte Verbindung zu aufeinanderfolgenden Versuchen, sondern zu Versuchen, die auf 10 basieren. Sie lernen die Erkennung von 0, indem Sie 0 → 10 → 20 → 30 versuchen, und lernen die Erkennung von 1, indem Sie 1 → 11 → 21 versuchen.
Die durchschnittliche Erkennungsrate ist je nach Anzahl unterschiedlich. Irgendwann erkennen einige Modelle 0 möglicherweise gut und 9 möglicherweise nicht. Deshalb variieren die Wahrnehmungen und scheinen zu vibrieren.
Und während das Lernen fortschreitet, lernt das Modell einen sogenannten "idealen Wert". Die Fehlerrate erhöht sich ebenfalls. Dies liegt daran, dass beim Festigen des Idealwerts der Grad der Abweichung des Eingabewerts deutlicher wird als im neutralen Zustand. Schauen wir uns ein Beispiel für den Idealwert und den Grad der Abweichung an.
Die obige Abbildung zeigt das Ergebnis der Eingabe eines Teils des 0-Validierungssatzes und dessen Fehlerrate. Die Fehlerrate ist der letzte Teil des Unterstrichs im Dateinamen vor der Erweiterung. Die Indexnummer des Bildes liegt vor der Fehlerrate. In diesem Bild zeigt das 93. Eingabebild die höchste Fehlerrate (0,4708). Das Modell erfuhr, dass es schwer zu erkennen war, dass es 0 war, als ich diese stumpfe Form sah. Im obigen Bild hat Nr. 98 auch die niedrigste Fehlerrate, so dass auch gelernt wird, dass 0 nach rechts geneigt der idealen Form von 0 am nächsten kommt.
Diesmal habe ich eine einfache Implementierung eines neuronalen Netzes gezeigt. Mit dem aktuellen Algorithmus gibt es jedoch immer noch Unzufriedenheiten hinsichtlich der Anzahl der Schulungen und Fehler. Nächstes Mal werde ich diese Unzufriedenheit mit mehreren Ansätzen lösen.
Recommended Posts