Comments 33
Очень похоже, что без нормализации (а вы вроде бы её не делаете после перемешивания) функции активации не отрабатывают так как прежде.
Выложите полный код пожалуйста.
Непонятно, обучение происходит на исходных нормализованных данных, а потом вы сети скармливаете ненормализованные данные?
Но это надо проверять экспериментально.
Причина довольно-таки очевидна — и автор явно её понимал ещё до начала эксперимента. Сеть не знает, как обобщать данные, и выбирает какой-то свой метод. Если бы была огромная обучающая выборка, включающая в себя все виды написания (в т.ч. как во втором примере) — всё было бы хорошо, но раз её нет — надо вносить информацию о желаемых принципах обобщения (явно, строя входные данные для сети, или неявно, создавая искусственную обучающую выборку из искажённых образов исходной).
Причина довольно-таки очевидна
Это да, но у вас она указана неправильно :) Как раз в обучающей выборке были цифры, написанные именно так, как в тестовой — но всё равно распознать их у сети не получилось.
from keras.datasets import mnist # subroutines for fetching the MNIST dataset
from keras.models import Model # basic class for specifying and training a neural network
from keras.layers import Input, Dense # the two types of neural network layer we will be using
from keras.utils import np_utils # utilities for one-hot encoding of ground truth values
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
batch_size = 128 # in each iteration, we consider 128 training examples at once
num_epochs = 16
hidden_size_1 = 512 # there will be 512 neurons in both hidden layers
hidden_size_2 = 512 # there will be 512 neurons in both hidden layers
height, width, depth = 28, 28, 1 # MNIST images are 28x28 and greyscale
num_classes = 10 # there are 10 classes (1 per digit)
(X_train, y_train), (X_test, y_test) = mnist.load_data() # fetch MNIST data
num_train, width, depth = X_train.shape # there are 50000 training examples in mnist
num_test = X_test.shape[0] # there are 10000 test examples in mnist
num_classes = np.unique(y_train).shape[0] # there are 10 image classes
#Visualizing
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_train)))
I_train.append(i)
axes[k].set_axis_off()
axes[k].imshow(X_train[i:i+1][0], cmap='gray')
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][0], cmap='gray')
perm = np.array([153, 17, 7, 148, 191, 15, 73, 109, 180, 129, 2, 218, 122,
151, 227, 167, 40, 248, 66, 212, 197, 101, 211, 139, 234, 133,
168, 174, 53, 207, 219, 37, 246, 194, 239, 255, 107, 90, 22,
44, 215, 84, 102, 201, 61, 176, 72, 125, 56, 99, 156, 161,
226, 6, 238, 52, 27, 50, 216, 231, 71, 5, 25, 34, 62,
29, 166, 253, 220, 3, 24, 225, 130, 196, 113, 86, 150, 209,
65, 195, 1, 200, 41, 81, 69, 163, 33, 147, 230, 202, 232,
112, 241, 137, 47, 187, 203, 175, 229, 39, 160, 186, 152, 222,
14, 85, 21, 77, 210, 108, 193, 250, 54, 45, 92, 141, 94,
208, 110, 192, 228, 115, 91, 143, 26, 88, 96, 170, 78, 87,
132, 172, 247, 178, 205, 165, 177, 144, 83, 49, 11, 67, 82,
134, 245, 100, 18, 48, 136, 213, 105, 162, 199, 103, 252, 214,
158, 189, 149, 95, 164, 111, 233, 181, 142, 249, 9, 236, 38,
173, 243, 57, 28, 128, 55, 32, 116, 59, 145, 97, 35, 106,
43, 206, 198, 60, 135, 74, 23, 76, 251, 120, 240, 75, 20,
169, 179, 121, 80, 217, 123, 235, 126, 114, 16, 155, 146, 119,
19, 8, 51, 98, 42, 185, 127, 93, 190, 104, 224, 171, 244,
124, 89, 68, 0, 4, 117, 182, 70, 64, 159, 157, 242, 188,
10, 30, 36, 58, 138, 118, 204, 184, 221, 13, 254, 31, 12,
140, 63, 223, 79, 46, 154, 183, 131, 237])
"""
perm = np.array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16])
"""
#perm = np.arange(28*28)
#perm = np.random.permutation(256)
X_train = X_train.reshape(num_train, height * width)
X_test = X_test.reshape(num_test, height * width)
XX_test = np.copy(X_test)
XX_train = np.copy(X_train)
for j in xrange(X_test.shape[1]):
for i in xrange(X_test.shape[0]):
X_test[i][j] = perm[XX_test[i][j]]
for i in xrange(X_train.shape[0]):
X_train[i][j] = perm[XX_train[i][j]]
X_train = X_train.reshape(num_train, height, width)
X_test = X_test.reshape(num_test, height, width)
#Visualizing
fig, axes = plt.subplots(1,10,figsize=(10,10))
for k in range(10):
i = I_train[k]
axes[k].set_axis_off()
axes[k].imshow(X_train[i:i+1][0], cmap='gray')
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(X_test[i:i+1][0], cmap='gray')
X_train = X_train.reshape(num_train, height * width) # Flatten data to 1D
X_test = X_test.reshape(num_test, height * width) # Flatten data to 1D
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= np.max(X_train) # Normalise data to [0, 1] range
X_test /= np.max(X_test) # Normalise data to [0, 1] range
Y_train = np_utils.to_categorical(y_train, num_classes) # One-hot encode the labels
Y_test = np_utils.to_categorical(y_test, num_classes) # One-hot encode the labels
inp = Input(shape=(height * width,)) # Our input is a 1D vector of size 784
hidden_1 = Dense(hidden_size_1, activation='relu')(inp) # First hidden ReLU layer
hidden_2 = Dense(hidden_size_2, activation='relu')(hidden_1) # Second hidden ReLU layer
out = Dense(num_classes, activation='softmax')(hidden_2) # Output softmax layer
model = Model(input=inp, output=out) # To define a model, just specify its input and output layers
model.compile(loss='categorical_crossentropy', # using the cross-entropy loss function
optimizer='adam', # using the Adam optimiser
metrics=['accuracy']) # reporting the accuracy
model.fit(X_train, Y_train, # Train the model using the training set...
batch_size=batch_size, nb_epoch=num_epochs,
verbose=1, validation_split=0.1) # ...holding out 10% of the data for validation
model.evaluate(X_test, Y_test, verbose=1) # Evaluate the trained model on the test set!
Перемешивание производится на исходных и нормализация происходит.
Я не переоцениваю свои знания в области ИИ, но объяснения у меня нет. Для данной сети все точки равноправны и все значения равноправны в исходном сигнале.
ru.wikipedia.org/wiki/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D0%93%D0%B0%D0%B1%D0%BE%D1%80%D0%B0
до скармливания данных сетке. Думаю, результат существенно улучшится.
Видя с десяток цифр рядом с друг другом мы «морально» повышаем шансы того что любой знак из этого ряда тоже является цифрой
Ну так эта нейросеть и настроена специально на разгадывание циферок. У нее контекст всегда один.
не даром детей обучают счёту с шести лет
Да, только как выглядят цифры и буквы они запоминают гораздо раньше. И чтобы запомнить, им достаточно увидеть их несколько раз.
>> «гораздо раньше.»
вот именно по этому у моих сверстников было большое преимущество надо мной. Мне лично в детстве не приходила в голову разглядывать значки написанные на упаковках и других местах и придавать им значения — хотя меня они буквально окружали…
>> настроена специально
— на паре примеров то? Человек в силу того что его голова не статична — вынужден видеть знаки под всеми возможными углами и в сочетании со всеми возможными вариантами расцветок. Сеть же тренировали на простом белом изображении знаков — как ей догадаться что речь идёт об одних и тех же цифрах когда буквально мы им поменяли цвет?
Умение не только видеть, но и различать, сопоставлять, отсеивать — этим мозг и отличается. А делает он это потому что у него большой запас таких знаний. Вот в самом последнем напримере самая первая четвёрка является именно четвёркой а не единицей, несмотря на то что там тоже есть вертикальная черта… И на чёрном фоне я это хорошо определяю, но в «взбалтанном» режиме я сначала предположил что это единица с шумом.
У вас вообще были дети? если нет — посмотрите видео ролики в интернете о детях которые учатся читать… Многие дети буквально «залипают» на некоторых буквах… Но потом всё же часто называют правильную. А всё почему?
Вы пробывали изучить язык символы которого вы почти не видели за свою жизнь? например японские. Я с легкостью выучил с десяток символов потому что они мне напоминали что либо… т.е. я построил ассоциации. Но с другой стороны я постоянно путаю многие другие символы. Просто не могу запомнить и всё. И не надо тут говорить «достаточно увидеть их несколько раз.» — несколько раз это только для пары символов. И то не факт что вы его запомните. И даже научившись читать хирагану и увидать вдруг её же но в тетрадке какого нибудь японского школьника вы всё равно встанете в ступор. И единственный способ понять что написано — искать какие то приметы, отсеивать неподходящие, и конечно контекст. Только так…
Сеть же тренировали на простом белом изображении знаков — как ей догадаться что речь идёт об одних и тех же цифрах когда буквально мы им поменяли цвет?
Нет, её тренировали на картинках, обработанных таким же образом, как и тестовые.
Давайте не путать буквы, обозначающие звуки, которых десятки, и иероглифы, обозначающие слова, которых тысячи. Речь идет о 10 цифрах.
Человек в силу того что его голова не статична — вынужден видеть знаки под всеми возможными углами и в сочетании со всеми возможными вариантами расцветок.
Нет. Запомнив черную цифру на белом фоне, человек узнает ее нарисованную синим на зеленом, даже если он раньше вообще не видел ни ее ни такое сочетание цветов, а также в виде разного размера и деформации.
А делает он это потому что у него большой запас таких знаний.
Нет. Потому что у него другие принципы работы. Которые впрочем частично пересекаются с используемыми в нейросетях.
PS. Заголовок, как обычно, очень желтушный.
Т.е. скоро возникнет проблема с нехваткой данных
Аугментация, не?
Не понял где тут блеск, и уж тем более не понял в чем нищета…
Ну, про блеск как раз в посте написано, вполне очевидными словами — в том, что человек не может распознать некоторые виды изображений ("карты звездного неба") на таком же уровне, как данный ИИ.
Вы, наверное, аудиоплееры тоже ИИ называете? Человек же не может распознать звук в том наборе байт, что приходит им на вход, верно?
Я лишь пояснил, что автор назвал блеском. Вот точная цитата:
Никакой человек с такой задачей на таких перемешанных картинках никогда не справится. Это блеск!!! Это феноменально по сравнению с человеком. Искать большую медведицу и стрельца нужно тысячелетиями.
Каким боком тут мое мнение о том, что такое ИИ?
И человек сможет, если ему так же "рецепторы переставить в глазе" так как сделал автор. По сути данные не поменялись. Просто договорились о том что их порядок поменяется, сеть спокойно и обучилась выдав тот же результат что и без пермутаций. А вторые два случая: причины такого результата в Relu (пороговая функция) которую пытаются использовать на одномерном слое, без учета соседних пикселей.
Если закрыть глаза на то, что теперь это знают «почти все» или поменять условия, то ответ на «объясните почему так» выглядит хорошей проверкой как на знание принципов, так и на умение соображать.
Блеск и нищета Искусственного Интеллекта