Algoritmo CNN para el reconocimiento de dígitos escritos a mano (conjunto de datos MNIST)

El proceso básico se muestra en la siguiente figura:

x (el valor de la característica de la imagen) : Aquí, se utiliza una columna de datos de 28*28=784 para representar la composición de una imagen, es decir, cada punto es una característica de la imagen, que en realidad es más fácil de entienda, porque cada punto A tendrá un impacto en la apariencia de la imagen y el significado de la expresión, pero la magnitud del impacto es diferente.

W (el peso correspondiente al valor de la característica) : este valor es muy importante. Después de una serie de entrenamientos, se obtiene el peso de la influencia de cada característica en el resultado. Nuestro entrenamiento es para obtener este valor de peso óptimo.

b (sesgo) : para la delinealización.

y (resultado predicho) : la probabilidad de qué número se predice para una sola muestra, por ejemplo: el resultado posible es [ 1,07476616 -4,54194021 2,98073649 -7,42985344 3,29253793 1,96750617 8,59438515 -6,65950203 1,6 872 1473 -0.9658531 ], significa 0, 1, 2 respectivamente, la probabilidad de 3, 4, 5, 6, 7, 8, 9, y luego se tomará un valor máximo como resultado de esta predicción.Para esta matriz, el resultado es 6 (8.59438515)

y_ (resultado real): valor de etiqueta, del conjunto de entrenamiento MNIST, el valor real correspondiente a cada imagen, como 1 se expresa como: [0 1 0 0 0 0 0 0 0 0], también llamado vector one-hot ( uso Los valores discretos representan características individuales).

MNIST ( Base de datos mixta del Instituto Nacional de Estándares y Tecnología ) es un conjunto de datos de visión por computadora y un conjunto de datos de referencia para el aprendizaje automático. Pertenece a los datos de aplicación de nivel de entrada del aprendizaje automático . El conjunto de datos MNIST fue creado por Yann  LeCun et al. en la investigación del aprendizaje automático Se usa muy comúnmente en , que contiene 70,000 imágenes escritas a mano con una longitud de 28 píxeles y un ancho de 28 píxeles, y cada imagen es solo en blanco y negro .

Contiene las siguientes cuatro partes:

(1) Imágenes del conjunto de entrenamiento: train-images-idx3-ubyte.gz (9,9 MB, que contiene 60 000 muestras).

(2) Etiquetas de clase del conjunto de entrenamiento: train-labels-idx1-ubyte.gz (29 KB, que contiene 60 000 etiquetas de clase).

(3) Imagen del conjunto de prueba: t10k-images-idx3-ubyte.gz (1,6 MB, que contiene 10000 muestras).

(4) Etiquetas del equipo de prueba: t10k-labels-idx1-ubyte.gz (5 KB, incluidas 1000 etiquetas).

El conjunto de datos del MNIST se construye a partir de dos conjuntos de datos del NIST de EE. UU. Las imágenes manuscritas en el conjunto de capacitación provienen de las manos de 250 personas, el 50 % de las cuales son estudiantes de secundaria y el 50 % restante son de la Oficina del Censo. Las imágenes en el conjunto de prueba también fueron escritas a mano en la misma escala por estudiantes de secundaria y personas seleccionadas por la Oficina del Censo.

Cada imagen tiene una etiqueta correspondiente al número que representa. La información de datos de imagen se almacena en el archivo de imagen y la información de datos de etiqueta se almacena en el archivo de etiqueta de clase.

El conjunto de datos se divide en dos categorías : un conjunto de entrenamiento de 60.000 filas y un conjunto de prueba de 10.000 filas . El conjunto de entrenamiento se divide en 55000 filas de datos de entrenamiento y 5000 filas de datos de validación . El conjunto de entrenamiento es un tensor (tensor) con una forma de [60000 , 784] La primera dimensión 6000 se usa para indexar la imagen, y la segunda dimensión 7 84 es 2 8 * 28 , que es el punto de píxel de la imagen. en MNIST , que se utiliza para indexar el píxel de la imagen.

Hay diez categorías de etiquetas, 0~9 , que se utilizan para indicar el número correspondiente a cada imagen . ¿Cuál es el número en la imagen? Entonces, el número de dimensión de la etiqueta es 1. Usando una codificación one-hot, expresada como un vector de diez dimensiones, por ejemplo , ([0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0]) se usa para representar la etiqueta 1, y la etiqueta es un [60000 , 10] para la matriz numérica. 

MNIST se puede visualizar: 

import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./MNIST_data", one_hot=False)
fig, ax_big = plt.subplots()
for i in range(10):  
# 读取十张
    x, y = mnist.test.next_batch(1)
    x = x.reshape([28, 28])
    ax = fig.add_subplot(2, 5, i + 1)  
# 以2行5列形式展示
    ax.imshow(x, cmap=plt.cm.gray)
    ax.set_xticks([])
    ax.set_yticks([])
# 隐藏子图坐标轴刻度
ax_big.set_xticks([])
# 隐藏坐标轴刻度
ax_big.set_yticks([])
plt.show()

Visualice 10 imágenes en escala de grises MNIST de la siguiente manera: 

Las notas se adjuntan a lugares que pueden no entenderse, codifique:

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
from tensorflow.examples.tutorials.mnist import input_data  # download and extract the data set automatically

# 初始化参数
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    # shape是必选项,输出张量维度,stddev=0.1用于设置正态分布被截断前的标准差
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    # 开始时设置为0.1
    return tf.Variable(initial)

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# ksize为卷积核大小  padding取valid时卷积之后图像大小为N=(imgSize-ksize)/strides
# x 表示输入图像,要求是一个tensor具有[batch,in_height,in_width,in_channels]这样的shape,为float32或者64
# 过滤器要求是一个tensor,具有[filter_height,filter_width,in_channels,out_channels]这样的shape

# get the data source
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# tf.name_scope()和tf.variable_scope()是两个作用域,
# 一般与两个创建/调用变量的函数tf.variable() 和tf.get_variable()搭配使用,用于变量共享
# input image:pixel 28*28 = 784
with tf.name_scope('input'):
    x = tf.placeholder(tf.float32, [None, 784])
    y_ = tf.placeholder('float', [None, 10])  # y_ is realistic result
# 创建占位符是 tf 读取数据的一种方法,让python代码来提供数据

with tf.name_scope('image'):
    x_image = tf.reshape(x, [-1, 28, 28, 1])  # -1表示由实际情况来定,图像数目*宽*高/28/28/1=第一维数
    tf.summary.image('input_image', x_image, 8)
    # 输出带图像的probuf,汇总数据的图像的的形式如下: ’ tag /image/0’, ’ tag /image/1’…,如:input/image/0等

# the first convolution layer
with tf.name_scope('conv_layer1'):
    W_conv1 = weight_variable([5, 5, 1, 32])  # convolution kernel: 5*5*1, number of kernel: 32
    b_conv1 = bias_variable([32])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # make convolution, output: 28*28*32

with tf.name_scope('pooling_layer'):
    h_pool1 = max_pool_2x2(h_conv1)  # make pooling, output: 14*14*32

# the second convolution layer
with tf.name_scope('conv_layer2'):
    W_conv2 = weight_variable([5, 5, 32, 64])  # convolution kernel: 5*5, depth: 32, number of kernel: 64
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)  # output: 14*14*64

with tf.name_scope('pooling_layer'):
    h_pool2 = max_pool_2x2(h_conv2)  # output: 7*7*64


# the first fully connected layer
with tf.name_scope('fc_layer3'):
    W_fc1 = weight_variable([7 * 7 * 64, 1024])
    b_fc1 = bias_variable([1024])  # size: 1*1024
    h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)  # output: 1*1024

# dropout
with tf.name_scope('dropout'):
    keep_prob = tf.placeholder(tf.float32)
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)


# the second fully connected layer
# train the model: y = softmax(x * w + b)
with tf.name_scope('output_fc_layer4'):
    W_fc2 = weight_variable([1024, 10])
    b_fc2 = bias_variable([10])  # size: 1*10

with tf.name_scope('softmax'):
    y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  # output: 1*10

with tf.name_scope('lost'):
    cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))   # 交叉熵计算损失函数
    tf.summary.scalar('lost', cross_entropy)

with tf.name_scope('train'):
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
    # AdamOptimizer是tensorflow中的一种优化器,1e-4是学习率
    # 为了最小化损失函数,需要用到反向传播思想,随机梯度下降算法来最小化损失函数

with tf.name_scope('accuracy'):
    correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    tf.summary.scalar('accuracy', accuracy)  # 显示标量信息
    '''
    tf.argmax(y_conv, 1) 是返回第二维(行方向)上最大值的索引,
    tf.equal() 是比较两个值是否相等,返回一个 bool 值(True or False),
    tf.cast() 是将bool 值转换为 1.0 or 0.0 的浮点类型,
    tf.reduce_mean() 是计算平均值。
    '''

merged = tf.summary.merge_all()
train_summary = tf.summary.FileWriter(r'C:\Users\12956\Anaconda3\Lib\site-packages', tf.get_default_graph())
# 将这里的地址路径改成tensorboard文件夹的绝对路径地址

# init all variables
init = tf.global_variables_initializer()
# 进行初始化,之前只是定义variable

# run session
with tf.Session() as sess:
    sess.run(init)
    # 构建一个session,在session中运行
    # train data: get w and b
    for i in range(2000):  # train 2000 times
        batch = mnist.train.next_batch(50)
        # 批量给网络提供数据

        result, _ = sess.run([merged, train_step], feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
        # 在mnist数据集中,0是输入的图片,1是输入的标签,这个batch是784*10的
        # train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

        if i % 100 == 0:
            # train_accuracy = sess.run(accuracy, feed_dict)
            train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})  # no dropout
            print('step %d, training accuracy %g' % (i, train_accuracy))

            # result = sess.run(merged, feed_dict={x: batch[0], y_: batch[1]})
            train_summary.add_summary(result, i)

    train_summary.close()

    print('test accuracy %g' % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))


 

Supongo que te gusta

Origin blog.csdn.net/baidu_41774120/article/details/117380864
Recomendado
Clasificación