CNNs, die Faltung verwenden, sind relativ gut darin, Merkmale in zweidimensionalen Schwarzweißbildern zu extrahieren. Ein Schwarzweißbild ist ein QR-Code. Lassen Sie uns also sehen, ob der Wert dieses QR-Codes von CNN gelesen werden kann. Eigentlich kann welches Bit in Schwarzweiß welcher Wert auf Regelbasis gelesen werden, und NN ohne Faltung ist ausreichend, aber hier wage ich es, CNN zu verwenden.
Die QR-Code-Version hängt von der Größe des QR-Codes und der Anzahl der darin enthaltenen Zeichen ab. Zum Beispiel ist Version = 1 21x21 groß und kann "www.wikipedia.org" und eine 17-stellige Zeichenfolge enthalten, wie unten gezeigt. Da es sich bei E1 bis E7 um Fehlerkorrekturen handelt, ist das Lesen nicht unbedingt erforderlich. Mit anderen Worten, in diesem Fall besteht jedes Zeichen aus 8 Bit. Wenn Sie also den Wert von insgesamt 136 Bit überprüfen, können Sie lesen, was in dieser Größe geschrieben ist, auch auf der Regelbasis. Derzeit besteht der Zweck darin, die auf diesem Mindest-QR-Code 21x21 geschriebenen Zahlen zu lesen.
Ich habe folgendes in Keras geschrieben. Ich habe die 6-stellige Zahl in eine Zeichenkette umgewandelt und 40.000 QR-Codes mit der kleinsten Größe erstellt, die als Trainings- und Testdaten verwendet werden können. Wenn es sich um das ursprüngliche CNN handelt, kann es auch erforderlich sein, Pooling zu verwenden, um die Bildgröße zu halbieren. In diesem Fall beträgt die Eingabegröße jedoch nur 21 × 21, sodass conv2d allein den Faltungsteil darstellt.
qr.py
import qrcode
import numpy as np
import random
from keras.utils import np_utils
from keras.layers import Input, Conv2D, MaxPooling2D, AveragePooling2D, BatchNormalization, Concatenate
from keras.models import Model
batch_size = 128
num_classes = 10
epochs = 30
X, Y = [], []
sample_list = random.sample(range(10**6), k=40000)
for i in sample_list:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=1, border=0 )
qr.add_data('%06d' % (i))
qr.make()
img = qr.make_image()
X.append(np.asarray(img))
Y.append([int(d) for d in format(i, '06d')])
X = np.reshape(np.asarray(X),(-1,21,21,1))/1.0
Y = np.reshape(np_utils.to_categorical(np.asarray(Y)), (-1,1,6,10))
print(X.shape)
print(Y.shape)
inputs = Input((21,21,1))
x = Conv2D(256, (3,3), padding='same', activation='relu')(inputs)
x = BatchNormalization()(x)
x = Conv2D(256, (3,3), padding='same', activation='relu')(x)
x = BatchNormalization()(x)
x = Conv2D(256, (3,3), padding='same', activation='relu')(x)
x = BatchNormalization()(x)
x = Conv2D(256, (3,3), padding='same', activation='relu')(x)
x = BatchNormalization()(x)
x = Conv2D(256, (3,3), padding='same', activation='relu')(x)
x = BatchNormalization()(x)
x = Conv2D(512, (3,3), padding='same', activation='relu')(x)
x = BatchNormalization()(x)
x = Conv2D(512, (3,3), padding='same', activation='relu')(x)
x = MaxPooling2D(pool_size=(21, 21))(x)
y = [Conv2D(10, (1,1), activation='softmax')(x) for i in range(6)]
y = Concatenate(axis=-2)(y)
model = Model(inputs=inputs, outputs=y)
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
history = model.fit(X[:30000], Y[:30000], batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X[30000:], Y[30000:]))
model.save('qr_model.h5', include_optimizer=False)
Hier
qr.py
y = [Conv2D(10, (1,1), activation='softmax')(x) for i in range(6)]
y = Concatenate(axis=-2)(y)
Sie können den Teil wie folgt schreiben.
qr.py
y1 = Conv2D(10, (1,1), activation='softmax')(x)
y2 = Conv2D(10, (1,1), activation='softmax')(x)
y3 = Conv2D(10, (1,1), activation='softmax')(x)
y4 = Conv2D(10, (1,1), activation='softmax')(x)
y5 = Conv2D(10, (1,1), activation='softmax')(x)
y6 = Conv2D(10, (1,1), activation='softmax')(x)
y = Concatenate(axis=-2)([y1,y2,y3,y4,y5,y6])
Das Ergebnis der Codeausführung ist zu diesem Zeitpunkt wie folgt.
(40000, 21, 21, 1)
(40000, 1, 6, 10)
...
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) (None, 21, 21, 1) 0
__________________________________________________________________________________________________
conv2d_1 (Conv2D) (None, 21, 21, 256) 2560 input_1[0][0]
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 21, 21, 256) 1024 conv2d_1[0][0]
__________________________________________________________________________________________________
conv2d_2 (Conv2D) (None, 21, 21, 256) 590080 batch_normalization_1[0][0]
__________________________________________________________________________________________________
batch_normalization_2 (BatchNor (None, 21, 21, 256) 1024 conv2d_2[0][0]
__________________________________________________________________________________________________
conv2d_3 (Conv2D) (None, 21, 21, 256) 590080 batch_normalization_2[0][0]
__________________________________________________________________________________________________
batch_normalization_3 (BatchNor (None, 21, 21, 256) 1024 conv2d_3[0][0]
__________________________________________________________________________________________________
conv2d_4 (Conv2D) (None, 21, 21, 256) 590080 batch_normalization_3[0][0]
__________________________________________________________________________________________________
batch_normalization_4 (BatchNor (None, 21, 21, 256) 1024 conv2d_4[0][0]
__________________________________________________________________________________________________
conv2d_5 (Conv2D) (None, 21, 21, 256) 590080 batch_normalization_4[0][0]
__________________________________________________________________________________________________
batch_normalization_5 (BatchNor (None, 21, 21, 256) 1024 conv2d_5[0][0]
__________________________________________________________________________________________________
conv2d_6 (Conv2D) (None, 21, 21, 512) 1180160 batch_normalization_5[0][0]
__________________________________________________________________________________________________
batch_normalization_6 (BatchNor (None, 21, 21, 512) 2048 conv2d_6[0][0]
__________________________________________________________________________________________________
conv2d_7 (Conv2D) (None, 21, 21, 512) 2359808 batch_normalization_6[0][0]
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D) (None, 1, 1, 512) 0 conv2d_7[0][0]
__________________________________________________________________________________________________
conv2d_8 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_9 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_10 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_11 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_12 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_13 (Conv2D) (None, 1, 1, 10) 5130 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
concatenate_1 (Concatenate) (None, 1, 6, 10) 0 conv2d_8[0][0]
conv2d_9[0][0]
conv2d_10[0][0]
conv2d_11[0][0]
conv2d_12[0][0]
conv2d_13[0][0]
==================================================================================================
Total params: 5,940,796
Trainable params: 5,937,212
Non-trainable params: 3,584
__________________________________________________________________________________________________
Train on 30000 samples, validate on 10000 samples
Epoch 1/30
30000/30000 [==============================] - 66s 2ms/step - loss: 2.7801 - acc: 0.1714 - val_loss: 2.3467 - val_acc: 0.2484
Epoch 2/30
30000/30000 [==============================] - 62s 2ms/step - loss: 1.8426 - acc: 0.3493 - val_loss: 1.6885 - val_acc: 0.3941
Epoch 3/30
30000/30000 [==============================] - 64s 2ms/step - loss: 1.4841 - acc: 0.4555 - val_loss: 1.4549 - val_acc: 0.4547
...
Epoch 28/30
30000/30000 [==============================] - 64s 2ms/step - loss: 0.0401 - acc: 0.9868 - val_loss: 0.3695 - val_acc: 0.9110
Epoch 29/30
30000/30000 [==============================] - 64s 2ms/step - loss: 0.0435 - acc: 0.9853 - val_loss: 0.3403 - val_acc: 0.9184
Epoch 30/30
30000/30000 [==============================] - 63s 2ms/step - loss: 0.0339 - acc: 0.9889 - val_loss: 0.3164 - val_acc: 0.9231
Die endgültige Genauigkeit beträgt ** acc: 0,9889, val_acc: 0,9231 **. Die Epoche und das Modell sind geeignet, daher verbessert eine Anpassung die Genauigkeit ein wenig mehr.
Schreiben Sie Folgendes als Bestätigungscode. Das Ergebnis ist eine relativ kleine, eingeschränkte Bedingung von 21 x 21 mit Version = 1 des QR-Codes, aber ich konnte bis zu einem gewissen Grad eine 6-stellige Zahl vorhersagen.
qr2.py
import qrcode
import numpy as np
import random
from keras.models import load_model
X, Y = [], []
sample_list = random.sample(range(10**6), k=10)
for i in sample_list:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=1, border=0 )
qr.add_data('%06d' % (i))
qr.make()
img = qr.make_image()
X.append(np.asarray(img))
Y.append(i)
X = np.reshape(np.asarray(X),(-1,21,21,1))/1.0
model = load_model('qr_model.h5')
Y_pred = model.predict(X)
Y_pred_list = []
for i in range(10):
Y_pred_value = 0
for j in range(6):
Y_pred_value += np.argmax(Y_pred[i,0,j])
Y_pred_value *= 10
Y_pred_list.append(Y_pred_value//10)
print(Y)
print(Y_pred_list)
[89127, 306184, 427806, 501649, 727976, 232504, 427216, 893062, 127368, 100207]
[89127, 306184, 427806, 501649, 727976, 234506, 431222, 893062, 127378, 100207]
Im Allgemeinen weiß MaxPooling2D, ob das Bild eine Funktion enthält, erreicht diese Position jedoch in nachfolgenden Ebenen nicht. Apropos CNN, es wird häufig für Klassifizierungsprobleme verwendet, z. B. wenn Hunde und Katzen irgendwo im Bild enthalten sind. Andererseits dachte ich, dass es möglich ist, Merkmale (ohne Verwendung von Abflachung) zu extrahieren, um den Ort anzugeben, aber es ist möglich Und es scheint. Dies kann daran liegen, dass die Merkmalsmenge des Datenorts durch den Datenwert in der Kurzstreckenfaltung und den Abstand vom quadratischen festen Muster oben links, oben rechts und unten links in der Fernfaltung extrahiert wird. Wenn Sie nur den Datenwert lesen (8 Bit von 2,4 oder 4,2), sollte Conv2d mit 2 Schichten (entspricht 5,5) ausreichen, aber in Wirklichkeit ist die Genauigkeit beim Modell mit Conv2d mit 2 Schichten nicht so hoch Es war (val_acc: ungefähr 0,5). Wenn Sie den QR-Code mit CNN lesen, kann es daher erforderlich sein, die Merkmalsmenge des Ortes durch Falten über große Entfernungen zu extrahieren. (Oder vielleicht ist es besser, Flatten schnell als Modell zu verwenden ...)
Recommended Posts