Red neuronal convolucional de TensorFlow Notes


prefacio

Se registra en tf1.x y tf2.x que la red neuronal convolucional se utiliza para completar la tarea multicategoría de reconocimiento de conjunto de datos CIFAR-10, y se continúa con el entrenamiento de punto de interrupción.


1. Red neuronal convolucional CNN

1. Red totalmente conectada: más parámetros, velocidad más lenta, sobreajuste
2. Red neuronal convolucional: cada capa está compuesta por múltiples planos bidimensionales, y cada plano está compuesto por múltiples neuronas independientes Capa de
entrada → (capa convolucional +→Capa de agrupación ?)+→Capa totalmente conectada+
(1) Capa convolucional: mejora las características, reduce el ruido

#卷积
y = tf.nn.conv2d(x, w, strides, padding) + b
'''
x:输入4维张量[batch,height,weight,channel]
w:[height,weight,input_channel,output_channel]
b:output_channel
strides:每一维步长
'''
#卷积层
tf.keras.layers.Conv2D(filters,#卷积核数目
					   kernel_size,#卷积核大小
          			   activation,#激活函数
          			   padding#填充方式))

Imagen⟶ imagen del mapa de características de la matriz de peso del núcleo de convolución \underset{matriz de peso}{\overset{núcleo de convolución}{\longrightarrow}}mapa de característicasimagenmatriz de pesonúcleo de convoluciónConexión local del mapa de características
, tamaño de paso de peso compartido
: el número de celdas móviles del kernel de convolución para obtener resultados de diferentes tamaños (reducción de muestreo)
[ N 1 , N 1 ] ⟶ [ N 1 , N 1 ] S [ ( N 1 ) − norte 2 ) / S + 1 , ( norte 1 − norte 2 ) / S + 1 ] [N1,N1]\underset{S}{\overset{[N1,N1]}{\longrightarrow}}[(N1- N2)/S+1,(N1-N2)/S+1][ N º 1 ,1 ]S[ N1 , N1 ] . _[( 1N 2 ) / S+1 ,( 1N 2 ) / S+1 ]
0 relleno: rellene los bordes con 0 para hacer que la entrada y la salida tengan el mismo tamaño
Convolución multicanal: use múltiples núcleos de convolución para extraer características
(2) Capa de reducción de resolución: reduzca los parámetros y reduzca el sobreajuste

#池化
y1 = tf.nn.max_pool(y, ksize, strides, padding)
'''
y:输入4维张量[batch,height,weight,channel]
ksize:池化窗口[1,height,weight,1]
'''
#池化层
tf.keras.layers.MaxPooling2D(pool_size)

Agrupación: calcule el valor promedio (característica de fondo) o el valor máximo (característica de textura) del área y fusione características

Dos, Tensorflow1.x

1. Cargue el conjunto de datos

Llamada CIFAR-10 conjunto de datos 10 clasificación 32x32RGB imágenes en color en tensorflow2.x
, conjunto de entrenamiento 50000, conjunto de prueba 10000
x_train: (50000, 32, 32, 3) y_train: (
10000, 1)
x_test: (10000, 32, 32, 3) )
prueba_y: (10000, 1)

import tensorflow as tf2
import matplotlib.pyplot as plt
import numpy as np
cifar10 = tf2.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#显示16张图片
def show(images, labels, preds):
    label_dict = {
    
    0:'plane', 1:'car', 2:'bird', 3:'cat',\
                  4:'deer', 5:'dog', 6:'frog', 7:'horse',\
                  8:'ship', 9:'trunk'}
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i], cmap='binary')
        label = label_dict[np.argmax(labels[i])]
        pred = label_dict[np.argmax(preds[i])]
        title = 'label:%s,pred:%s' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

2. Tratamiento de datos

import tensorflow.compat.v1 as tf
from sklearn.preprocessing import OneHotEncoder
from sklearn.utils import shuffle
from time import time
import os
tf.disable_eager_execution()

#维度转换,灰度值归一化,标签独热编码
x_train = (x_train/255.0).astype(np.float32)
x_test = (x_test/255.0).astype(np.float32)
y_train = OneHotEncoder().fit_transform(y_train).toarray()
y_test = OneHotEncoder().fit_transform(y_test).toarray()
#训练集50000个样本,取5000个样本作为验证集;测试集10000个样本
x_valid, y_valid = x_train[45000:], y_train[45000:]
x_train, y_train = x_train[:45000], y_train[:45000]

3. Definir el modelo

#输入层
#输入通道3,图像大小32*32
with tf.name_scope('Input'):
    x = tf.placeholder(tf.float32, [None, 32, 32, 3], name='X')
#卷积层1
#输出通道32,卷积核3*3,步长为1,图像大小32*32
with tf.name_scope('Conv_1'):
    w1 = tf.Variable(\
         tf.truncated_normal((3,3,3,32), stddev=0.1), name='W1')
    b1 = tf.Variable(tf.zeros(32), name='B1')
    y1 = tf.nn.conv2d(x, w1, strides=[1,1,1,1], padding='SAME') + b1
    y1 = tf.nn.relu(y1)
#池化层1
#输出通道32,最大值池化2*2,步长为2,图像大小16*16
with tf.name_scope('Pool_1'):
    y2 = tf.nn.max_pool(y1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#卷积层2
#输出通道64,卷积核3*3,步长为1,图像大小32*32
with tf.name_scope('Conv_1'):
    w3 = tf.Variable(\
         tf.truncated_normal((3,3,32,64), stddev=0.1), name='W3')
    b3 = tf.Variable(tf.zeros(64), name='B3')
    y3 = tf.nn.conv2d(y2, w3, strides=[1,1,1,1], padding='SAME') + b3
    y3 = tf.nn.relu(y3)
#池化层2
#输出通道64,最大值池化2*2,步长为2,图像大小8*8
with tf.name_scope('Pool_1'):
    y4 = tf.nn.max_pool(y3, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#全连接层
#输入8*8*64,128个神经元
with tf.name_scope('Output'):
    w5 = tf.Variable(\
         tf.truncated_normal((8*8*64, 128), stddev=0.1), name='W5')
    b5 = tf.Variable(tf.zeros((128)), name='B5')
    y5 = tf.reshape(y4, (-1, 8*8*64))
    y5 = tf.matmul(y5, w5) + b5
    y5 = tf.nn.relu(y5)
    y5 = tf.nn.dropout(y5, keep_prob=0.8)
#输出层
#输出10个神经元
with tf.name_scope('Output'):
    w6 = tf.Variable(\
         tf.truncated_normal((128, 10), stddev=0.1), name='W6')
    b6 = tf.Variable(tf.zeros((10)), name='B6')
    pred = tf.matmul(y5, w6) + b6
    #pred = tf.nn.softmax(y6)
#优化器
with tf.name_scope('Optimizer'):
    y = tf.placeholder(tf.float32, [None, 10], name='Y')
    loss_function = tf.reduce_mean(\
                    tf.nn.softmax_cross_entropy_with_logits(\
                    logits=pred, labels=y))
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001)\
                .minimize(loss_function)
#准确率
equal = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
accuracy = tf.reduce_mean(tf.cast(equal, tf.float32))

4. Modelo de formación

parámetros de entrenamiento

train_epoch = 10
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#损失函数与准确率
step = 0
display_step = 10
loss_list = []
acc_list = []
epoch = tf.Variable(0, name='epoch', trainable=False)
#变量初始化
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

Reanudar el entrenamiento

ckpt_dir = './ckpt_dir/cifar10'
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)
vl = [v for v in tf.global_variables() if 'Adam' not in v.name]
saver = tf.train.Saver(var_list=vl, max_to_keep=1)
ckpt = tf.train.latest_checkpoint(ckpt_dir)
if ckpt != None:
    saver.restore(sess, ckpt)
start_ep = sess.run(epoch)

entrenamiento iterativo

start_time = time()
for ep in range(start_ep, train_epoch):
    #打乱顺序
    x_train, y_train = shuffle(x_train, y_train)
    print('epoch:{}/{}'.format(ep+1, train_epoch))
    for batch in range(batch_num):
        xi = x_train[batch*batch_size:(batch+1)*batch_size]
        yi = y_train[batch*batch_size:(batch+1)*batch_size]
        sess.run(optimizer, feed_dict={
    
    x:xi, y:yi})
        step = step + 1
        if step % display_step == 0:
            loss, acc = sess.run([loss_function, accuracy],\
                                 feed_dict={
    
    x:x_valid, y:y_valid})
            loss_list.append(loss)
            acc_list.append(acc)
    #保存检查点
    sess.run(epoch.assign(ep+1))
    saver.save(sess, os.path.join(ckpt_dir,\
              'cifar10_model.ckpt'), global_step=ep+1)

5. Visualización de resultados

end_time = time()
y_pred, acc = sess.run([pred, accuracy],\
                        feed_dict={
    
    x:x_test, y:y_test})
fig2 = plt.figure(2, figsize=(12, 6))
ax = fig2.add_subplot(1, 2, 1)
ax.plot(loss_list, 'r-')
ax.set_title('loss')
ax = fig2.add_subplot(1, 2, 2)
ax.plot(acc_list, 'b-')
ax.set_title('acc')
print('用时%.1fs' % (end_time - start_time))
print('Accuracy:{:.2%}'.format(acc))
show(x_test[0:16], y_test[0:16], y_pred[0:16])

Interrumpido después del 8.º entrenamiento, vuelva a ejecutarse y comience a entrenar desde el 9.

La pérdida y la precisión en el conjunto de validación

Etiquetas y valores previstos de las primeras 16 imágenes


Dos, Tensorflow2.x

1. Cargue el conjunto de datos

Los valores de las etiquetas son números enteros, no codificados en caliente

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from time import time
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#显示16张图片
def show(images, labels, preds):
    label_dict = {
    
    0:'plane', 1:'car', 2:'bird', 3:'cat',\
                  4:'deer', 5:'dog', 6:'frog', 7:'horse',\
                  8:'ship', 9:'trunk'}
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i], cmap='binary')
        label = label_dict[labels[i]]
        pred = label_dict[preds[i]]
        title = 'label:%s,pred:%s' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

2. Tratamiento de datos

Sin división del conjunto de validación

#维度转换,灰度值归一化,标签独热编码
x_train = (x_train/255.0).astype(np.float32)
x_test = (x_test/255.0).astype(np.float32)

3. Definir el modelo

crear modelo

model = tf.keras.models.Sequential()
#添加层
model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=(3,3),\
          input_shape=(32,32,3), activation='relu', padding='same'))
model.add(tf.keras.layers.Dropout(rate=0.3))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3),\
          activation='relu', padding='same'))
model.add(tf.keras.layers.Dropout(rate=0.3))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(units=10,\
          kernel_initializer='normal', activation='softmax'))
#模型摘要
model.summary()

modelo de carga

'''
#加载模型(整个模型)
mpath = './model/cifar10.h5'
model.load_weights(mpath)
'''
#加载模型(检查点)
cdir = './model/'
ckpt = tf.train.latest_checkpoint(cdir)
if ckpt != None:
    model.load_weights(ckpt)

modo de entrenamiento

#整数类型作标签
model.compile(optimizer='adam',\
              loss='sparse_categorical_crossentropy',\
              metrics=['accuracy'])

4. Modelo de formación

#回调参数设置检查点与早停
cpath = './model/cifar10.{epoch:02d}-{val_loss:.4f}.H5'
callbacks = [tf.keras.callbacks.ModelCheckpoint(filepath=cpath,
                                                save_weights_only=True,
                                                verbose=1,
                                                save_freq='epoch'),
             tf.keras.callbacks.EarlyStopping(monitor='val_loss',
                                              patience=3)]
#模型训练
start_time = time()
history = model.fit(x_train, y_train,\
                    validation_split=0.2, epochs=10, batch_size=1000,\
                    callbacks=callbacks, verbose=1)
end_time = time()
print('用时%.1fs' % (end_time-start_time))

5. Visualización de resultados

history.history:
pérdida de datos de tipo de diccionario, precisión, val_loss, val_accuracy

fig2 = plt.figure(2, figsize=(12, 6))
ax = fig2.add_subplot(1, 2, 1)
ax.plot(history.history['val_loss'], 'r-')
ax.set_title('loss')
ax = fig2.add_subplot(1, 2, 2)
ax.plot(history.history['val_accuracy'], 'b-')
ax.set_title('acc')

evaluación del modelo

test_loss, test_acc = model.evaluate(x_train, y_train, verbose=1)
print('Loss:%.2f' % test_loss)
print('Accuracy:{:.2%}'.format(test_acc))

modelo de predicción

#分类预测
preds = model.predict_classes(x_test)
show(x_test[0:16], y_test[0:16].flatten(), preds[0:16])
#保存模型
#model.save_weights(mpath)

Estructura de la red

Guarde el modelo después del entrenamiento

Valor de pérdida de conjunto de validación y tasa de precisión

Valor de etiqueta y valor de predicción de las primeras 16 imágenes

Importe el modelo, la tasa de precisión es la misma que antes

Detenga el programa después del segundo lote de entrenamiento

Se mejora la tasa de precisión sobre la base de la formación previa
inserte la descripción de la imagen aquí

Resumir

La red neuronal convolucional puede extraer características de los datos, reducir la cantidad de parámetros y mejorar la velocidad de entrenamiento;
después de usar OneHotEncoder para la codificación one-hot, debe usar toarray() para convertirlo en una forma de matriz para participar en el operación;
cuando el tiempo de entrenamiento es largo, se puede guardar periódicamente para interrumpirlo Haga clic para continuar con el entrenamiento;
al guardar un punto de control en tf1.x, se guardarán varios pesos con el mismo nombre, pero es posible que no se guarden los pesos con Adam en el nombre guardado, y la consola debe reiniciarse antes y después de guardar para evitar que el nombre del peso no coincida al cargar.

Supongo que te gusta

Origin blog.csdn.net/qq_53715621/article/details/128784489
Recomendado
Clasificación