Предыдущая статья оставила ощущение недосказанности и две темы — блондинок и монстров не раскрыта были совсем.
Попробуем исправить и начнем с монстров.
Не секрет, что большинство систем распознавания используют ИИ для определения потенциальных кандидатов и нам тоже интересно проверить, как это у цифр.
Возьмем тот же mnist изученный вдоль и поперек и сверточную сеть с параметрами accuracy: 0.9939.
текст приложен, можно проверить (заимствован с сайта keras.io и немного модифицирован).
Нормальная точность, если epoch добавить, можно и 0.995.
from keras.datasets import mnist
from keras.layers import Input, Dense, Dropout, Conv2D, MaxPooling2D, Activation, Flatten
from keras.models import Sequential
from keras.optimizers import RMSprop
from keras.utils import np_utils
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
batch_size = 128
num_epochs = 16
hidden_size_1 = 512
hidden_size_2 = 512
height, width, depth = 28, 28, 1
num_classes = 10
(X_train, y_train), (X_test, y_test) = mnist.load_data()
num_train, width, depth = X_train.shape
num_test = X_test.shape[0]
num_classes = np.unique(y_train).shape[0]
X_save_test = np.copy(X_test)
X_train = np.expand_dims(X_train, axis=3)
X_test = np.expand_dims(X_test, axis=3)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255.
X_test /= 255.
Y_train = np_utils.to_categorical(y_train, num_classes)
Y_test = np_utils.to_categorical(y_test, num_classes)
import numpy as np
import keras as ks
model = Sequential()
model.add(Conv2D(16, (3, 3), padding='same',
input_shape=X_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(64, (5, 5)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(16, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (5, 5)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))
opt = ks.optimizers.adam(lr=0.0001, decay=0.01)
model.compile(loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy'])
history = model.fit(X_train, Y_train,
batch_size=256,
epochs=32,
verbose=0)
score = model.evaluate(X_test, Y_test, verbose=1)
print 'Train accuracy:', score[1]
print 'Train loss:', score[1]
Test accuracy: 0.9939
А теперь проделаем на тестовым набором пластическую операцию и покромсаем каждую букву ножиком 7х7.
это 25% от ширины и высоты — превратим цифры в монстров и посмотрим, как их распознает наша сеть
XX_test = np.copy(X_save_test)
I_train = list()
I_test = list()
fig, axes = plt.subplots(1,10,figsize=(10,10))
for k in range(10):
i = np.random.choice(range(len(X_test)))
I_test.append(i)
axes[k].set_axis_off()
axes[k].imshow(X_test[i:i+1,...].reshape(28,28), cmap='gray')
st = 7
for k in xrange(X_test.shape[0]):
for i in xrange(0,X_test.shape[1],st):
for j in xrange(0,X_test.shape[2],st):
XX_test[k,i:i+st,j:j+st] = np.random.permutation( XX_test[k,i:i+st,j:j+st])
XX_test = np.expand_dims(XX_test, axis=3)
XX_test = XX_test.astype('float32')
XX_test /= 255.
fig, axes = plt.subplots(1,10,figsize=(10,10))
for k in range(10):
i = I_test[k]
axes[k].set_axis_off()
axes[k].imshow(XX_test[i:i+1,...].reshape(28,28), cmap='gray')
score = model.evaluate(XX_test, Y_test, verbose=0)
print 'Test accuracy:', score[1]
результат довольно приличный — accuracy: 0.7051. Это мы каждую картинку случайно кромсали окном 7х7 при том, что сами они 28х28!
Видно на слайде, что некоторые цифры совсем уж искромсаны.
Но сеть справляется, не очень хорошо, но справляется. А если обучить с применением разных трюков из keras по сдвигу и изменению размеров, результат должен быть еще лучше.
Вывод такой:
— что бы скрыться от «большого брата» кромсать себя не нужно и бесполезно. Спасет не надолго.
Монстры для ИИ проблемы не представляют, сущность будет ему видна
А теперь к главной теме — блондинкам.
Попробуем просто перекрасить цифры, поскольку они greyscale, просто переставим в них цвета, так же как и в предыдущей статье. Но оставим обученную сеть как есть. Т.е. обучаем сеть на исходном mnist ничего не меняя, а тестовую последовательность перекрашиваем.
Напомню, что сеть обучена на нормальном mnist и выдает accuracy: 0.9939.
Но тестить будем блондинок — «крашенные цифры».
I_train = list()
I_test = list()
perm = np.array(
[237, 79, 8, 182, 190, 177, 33, 121, 250, 11, 128, 48, 246, 125, 63, 92, 236, 130,
151, 93, 149, 175, 87, 234, 126, 3, 139, 217, 251, 6, 220, 70, 176, 206, 152, 228,
74, 199, 88, 24, 188, 163, 31, 211, 171, 196, 109, 64, 40, 14, 17, 119, 91, 201,
76, 27, 59, 230, 30, 57, 146, 150, 85, 214, 248, 212, 38, 104, 233, 192, 81, 120,
96, 100, 54, 95, 168, 155, 144, 205, 72, 227, 122, 60, 112, 229, 223, 242, 117, 101,
158, 55, 90, 160, 244, 203, 218, 124, 52, 254, 39, 209, 102, 216, 241, 115, 142, 166,
75, 108, 197, 181, 47, 42, 15, 133, 224, 161, 50, 68, 222, 172, 103, 174, 194, 153,
210, 7, 232, 159, 65, 238, 1, 143, 9, 207, 62, 137, 78, 110, 89, 0, 113, 243,
46, 20, 157, 184, 239, 141, 80, 200, 204, 178, 13, 99, 247, 221, 49, 16, 191, 94,
19, 169, 86, 235, 98, 131, 71, 118, 252, 129, 34, 253, 69, 18, 189, 21, 134, 22,
136, 77, 66, 225, 105, 198, 82, 245, 165, 255, 35, 183, 127, 23, 45, 116, 167, 185,
67, 73, 180, 249, 226, 154, 43, 29, 148, 83, 56, 5, 123, 140, 106, 162, 84, 44,
138, 195, 170, 53, 215, 187, 219, 132, 164, 97, 32, 156, 41, 135, 58, 173, 193, 231,
4, 107, 213, 26, 240, 25, 208, 179, 2, 36, 51, 145, 37, 202, 12, 28, 114, 147,
61, 10, 186, 111])
XX_test = np.copy(X_save_test)
fig, axes = plt.subplots(1,10,figsize=(10,10))
for k in range(10):
i = np.random.choice(range(len(X_test)))
I_test.append(i)
axes[k].set_axis_off()
axes[k].imshow(X_test[i:i+1,...].reshape(28,28), cmap='gray')
for k in xrange(X_test.shape[0]):
for i in xrange(28):
for j in xrange(28):
XX_test[k,i,j] = perm[X_save_test[k,i,j]]
fig, axes = plt.subplots(1,10,figsize=(10,10))
for k in range(10):
i = I_test[k]
axes[k].set_axis_off()
axes[k].imshow(XX_test[i:i+1,...].reshape(28,28), cmap='gray')
XX_test = np.expand_dims(XX_test, axis=3)
XX_test = XX_test.astype('float32')
XX_test /= 255.
И тут наш супер интеллект вдруг проявил какие то непонятные наклонности и пристрастия:
score = model.evaluate(XX_test, Y_test, verbose=0)
print 'Test accuracy:', score[1]
Test accuracy: 0.1634
Результат accuracy: 0.1634 обескураживает.
На тестовых слайдах все отлично видно, понятно и ясно, но результат 0.1634 говорит о том, что сеть их всех, по видимому, определяет как одинаковую цифру и иногда отличает.
Так что, чтобы спрятаться от «Большого брата» не нужны супер пластические хирурги и кромсания.
Нужно всего то правильно наложить макияж.
PS. Извиняюсь за ассоциации, блондинок, монстров — это не специально и никого не хотел задеть. Весна, пятница — надеюсь меня оправдают
Автор: ChePeter