В учебных целях я написал нейронную сеть классификации цифр на основе хороших изображений из датасета Chars74k. Использовал я в основном TensorFlow, Keras использовал только для считывания изображений в массивы NumPy. У нейросети есть один свёрточный слой из свёртки 8х8 на 16 признаков, в качестве функции нелинейности используется ReLU, и подытоживается всё это слоем субдискредитации. Далее идёт обычный полносвязный слой с 4096 входами и 10 выходами. Путём подбора гиперпараметров точность достигает максимума 70%, а затем то возрастает, то падает. В чём может быть проблема? Проблема в архитектура сети (добавить или изменить слои) и/или в подборе гиперпараметров? Исходный код с датасетом можно просмотреть и тут:
https://bitbucket.org/smolyardev/chars74kimport numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing import image
import os
class Batch:
def __init__(self, data):
self.i = 0
self.data = data
self.data_len = len(data)
def next(self, step=100):
if self.i + step < self.data_len:
res = self.data[self.i:self.i + step]
self.i += step
else:
res = self.data[self.i:]
self.i = step - (self.data_len - self.i)
res.extend(self.data[:self.i])
return res
folder = 'data'
i = 0
train = []
for path in os.listdir(folder):
imgs = "{}/{}".format(folder, path)
if os.path.isdir(imgs) and path.startswith("Sample"):
for ipath in os.listdir(imgs):
img = "{}/{}".format(imgs, ipath)
if os.path.isfile(img) and img.endswith(".png"):
proc = image.load_img(img, target_size=(32, 32))
data = image.img_to_array(proc)
data /= 255
y_data = np.zeros(10)
y_data[i] = 1.
train.append({"x": data, "y": y_data})
i += 1
np.random.shuffle(train)
x = tf.placeholder(dtype=tf.float32, shape=(None, 32, 32, 3))
y = tf.placeholder(dtype=tf.float32, shape=(None, 10))
w1 = tf.Variable(tf.truncated_normal([8, 8, 3, 16], stddev=0.1))
b1 = tf.Variable(tf.constant(0., shape=[16]))
conv1 = tf.nn.conv2d(x, w1, strides=[1, 1, 1, 1], padding="SAME") + b1
h_conv1 = tf.nn.relu(conv1)
pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
flat1 = tf.reshape(pool1, [-1, 4096])
w2 = tf.Variable(tf.truncated_normal([4096, 10], stddev=0.1))
b2 = tf.Variable(tf.constant(0., shape=[10]))
h2 = tf.matmul(flat1, w2) + b2
y_conv = tf.nn.softmax(h2)
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_conv, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.25).minimize(cross_entropy)
correct = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
batch = Batch(train)
for i in range(2000):
next_tr = batch.next(100)
n_x = [t['x'] for t in next_tr]
n_y = [t['y'] for t in next_tr]
_, res = sess.run((train_step, accuracy), feed_dict={x: n_x, y: n_y})
if i % 100 == 0:
print(res)