Red neuronal de TensorFlow Notes completa múltiples tareas de clasificación


prefacio

Modifique la neurona única de las notas de TensorFlow para completar la tarea de clasificación múltiple y use la red neuronal en tf1.x y tf2.x para completar la tarea de clasificación múltiple de reconocimiento de dígitos escritos a mano.


1. Llamada de conjunto de datos

La llamada y el preprocesamiento del conjunto de datos son exactamente iguales que en el artículo anterior.

#数据集调用,在tensorflow2.x中调用数据集
import tensorflow as tf2
import matplotlib.pyplot as plt
import numpy as np
mnist = tf2.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
#维度转换,灰度值归一化,标签独热编码
x_train = x_train.reshape((-1, 784))
x_train = tf2.cast(x_train/255.0, tf2.float32)
x_test = x_test.reshape((-1, 784))
x_test = tf2.cast(x_test/255.0, tf2.float32)
y_train = tf2.one_hot(y_train, depth=10)
y_test = tf2.one_hot(y_test, depth=10)
#训练集训练模型,验证集调整超参数,测试集测试模型效果
#训练集60000个样本,取5000个样本作为验证集;测试集10000个样本
x_valid, y_valid = x_train[55000:], y_train[55000:]
x_train, y_train = x_train[:55000], y_train[:55000]
#显示16张图片
def show(images, labels, preds):
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i].reshape(28, 28), cmap='binary')
        label = np.argmax(labels[i])
        pred = np.argmax(preds[i])       
        title = 'label:%d,pred:%d' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

Dos, Tensorflow1.x

1. Capa oculta única

Definir el modelo
Agregar un conjunto de pesos como parámetros de capa oculta
La capa de salida no realiza softmax
Usar distribución normal truncada para reducir la desviación de los pesos aleatorios

import tensorflow.compat.v1 as tf
from sklearn.utils import shuffle
from time import time
tf.disable_eager_execution()
with tf.name_scope('Model'):
    x = tf.placeholder(tf.float32, [None, 784], name='X')
    y = tf.placeholder(tf.float32, [None, 10], name='Y') 
    #隐藏层
    with tf.name_scope('Hide'):
        h1_nn = 256
        #截断正态分布
        w1 = tf.Variable(\
             tf.truncated_normal((784, h1_nn), stddev=0.1), name='W1')
        b1 = tf.Variable(tf.zeros((h1_nn)), name='B1')
        y1 = tf.nn.relu(tf.matmul(x, w1) + b1)
    #输出层
    with tf.name_scope('Output'):
        w2 = tf.Variable(\
             tf.truncated_normal((h1_nn, 10), stddev=0.1), name='W2')
        b2 = tf.Variable(tf.zeros((10)), name='B2')
        pred = tf.matmul(y1, w2) + b2

Modelo de entrenamiento
Use una función de pérdida combinada con softmax para evitar valores de pérdida excesivos

#训练参数
train_epoch = 10
learning_rate = 0.1
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#损失函数与准确率
step = 0
display_step = 5
loss_list = []
acc_list = []
#结合softmax的损失函数
loss_function = tf.reduce_mean(\
                tf.nn.softmax_cross_entropy_with_logits(\
                logits=pred, labels=y))
equal = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
accuracy = tf.reduce_mean(tf.cast(equal, tf.float32))
#优化器
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss_function)
#变量初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    #tf转为numpy
    x_train = sess.run(x_train)
    x_valid = sess.run(x_valid)
    x_test = sess.run(x_test)
    y_train = sess.run(y_train)
    y_valid = sess.run(y_valid)
    y_test = sess.run(y_test)

Entrenamiento iterativo
Use time() para registrar el tiempo de entrenamiento

    start_time = time()
    for epoch in range(train_epoch):
        print('epoch:%d' % 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)
        #打乱顺序
        x_train, y_train = shuffle(x_train, y_train)

Visualización de resultados

    end_time = time()
    y_pred, equ_list, acc = sess.run([pred, equal, 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))
#展示预测错误的图片
err_list = [ not equ for equ in equ_list]
show(x_test[err_list], y_test[err_list], y_pred[err_list])

Precisión mejorada con respecto al uso de una sola neurona

Imágenes de mispredicted

2. Modelo de ahorro y llamada

Establecer directorio de puntos de control

import os
ckpt_dir = './ckpt_dir/'
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)

Los pesos generados al usar el optimizador de Adam no se guardan

vl = [v for v in tf.global_variables() if 'Adam' not in v.name]
saver = tf.train.Saver(var_list=vl)

Guarda el modelo después de cada ronda.

    for epoch in range(train_epoch):
        saver.save(sess, os.path.join(ckpt_dir,\
                   'mnist_model_%d.ckpt' % (epoch+1)))

Guarde el modelo después del entrenamiento

    saver.save(sess, os.path.join(ckpt_dir,\
              'mnist_model.ckpt'))

Mantenga los últimos 5 archivos, los archivos son más grandes y el tiempo de almacenamiento es más largo

Llame al modelo

from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
with tf.Session() as sess:
    ckpt_dir = './ckpt_dir/'
    saver = tf.train.Saver()
    #获取最新检查点
    ckpt = tf.train.get_checkpoint_state(ckpt_dir)
    #打印权重信息
    print_tensors_in_checkpoint_file(ckpt.model_checkpoint_path,\
            tensor_name=None, all_tensors=True, all_tensor_names=True)
    #恢复模型
    saver.restore(sess, ckpt.model_checkpoint_path)

Hay dos conjuntos de pesos Model y Model_1 en el modelo guardado, que son los pesos en el momento de la inicialización y los pesos después de la optimización: pero aquí
Model es el peso después del entrenamiento y

Model_1 es el peso en el momento de la inicialización

. la tasa de precisión es demasiado baja, puede inicializarse con , debe cambiar el nombre del modelo a Model_1. Después de guardar el modelo, es necesario salir de la consola actual y luego llamarla; de lo contrario, se puede informar un error.

with tf.name_scope('Model_1'):

Los resultados son consistentes con los obtenidos después del entrenamiento.

3. Tensorflow2.x

1. Clase de capa completamente conectada

definir modelo

import tensorflow as tf
from sklearn.utils import shuffle
from time import time
#全连接层
class fcn_layer():
    def __init__(self, input_dim, output_dim):
        self.w = tf.Variable(tf.random.truncated_normal(\
                            (input_dim, output_dim), stddev=0.1), tf.float32)
        self.b = tf.Variable(tf.zeros(output_dim), tf.float32)
    def cal(self, inputs, activation=None):
        y = tf.matmul(inputs, self.w) + self.b
        if activation != None:
            y = activation(y)
        return y

Red neuronal de tres capas 256x64x32

hide_1 = fcn_layer(784, 256)
hide_2 = fcn_layer(256, 64)
hide_3 = fcn_layer(64, 32)
out = fcn_layer(32, 10)
def model(x):
    y1 = hide_1.cal(x, tf.nn.relu)
    y2 = hide_2.cal(y1, tf.nn.relu)
    y3 = hide_3.cal(y2, tf.nn.relu)
    y4 = out.cal(y3, tf.nn.softmax)
    return y4

Función de pérdida y precisión

#损失函数
def loss_function(x, y):
    pred = model(x)
    loss = tf.keras.losses.categorical_crossentropy(\
           y_true=y, y_pred=pred)
    return tf.reduce_mean(loss)
#准确率
def accuracy(x, y):
    pred = model(x)
    acc = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
    acc = tf.cast(acc, tf.float32)
    return tf.reduce_mean(acc)
#梯度
def grad(x, y):
    with tf.GradientTape() as tape:
        loss = loss_function(x, y)
        return  tape.gradient(loss, w_list+b_list)
#待优化变量列表
w_list = [hide_1.w, hide_2.w, hide_3.w, out.w]
b_list = [hide_1.b, hide_2.b, hide_3.b, out.b]

modelo de entrenamiento

#训练参数
train_epoch = 10
learning_rate = 0.01
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#展示间隔
step = 0
display_step = 5
loss_list = []
acc_list = []
#Adam优化器
optimizer = tf.keras.optimizers.Adam(learning_rate)

entrenamiento iterativo

start_time = time()
for epoch in range(train_epoch):
    print('epoch:%d' % 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]
        grads = grad(xi, yi)
        optimizer.apply_gradients(zip(grads, w_list+b_list))
        step = step + 1
        if step % display_step == 0:
            loss_list.append(loss_function(x_valid, y_valid))
            acc_list.append(accuracy(x_valid, y_valid))
    #打乱顺序
    x_train, y_train = shuffle(x_train.numpy(), y_train.numpy())
    x_train = tf.cast(x_train, tf.float32)
    y_train = tf.cast(y_train, tf.float32)

Visualización de resultados

#验证集结果
end_time = time()
print('用时%.1fs' % (end_time - start_time))
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')
#测试集结果
acc = accuracy(x_test, y_test)
print('Accuracy:{:.2%}'.format(acc))
y_pred = model(x_test)
show(x_test.numpy(), y_test, y_pred)

La tasa de precisión de la red neuronal de tres capas se mejora aún más y el tiempo de entrenamiento también aumenta
inserte la descripción de la imagen aquí

2. Modelado Keras

Llamada de conjunto de datos

import tensorflow as tf
import matplotlib.pyplot as plt
from time import time
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

La conversión de dimensión se lleva a cabo en la capa plana, y la etiqueta adopta directamente un número entero, solo necesita normalizar el valor de gris y no necesita dividir el conjunto de verificación aquí.

x_train = tf.cast(x_train/255.0, tf.float32)
x_test = tf.cast(x_test/255.0, tf.float32)

Mostrar 16 fotos

def show(images, labels, preds):
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i].reshape(28, 28), cmap='binary')  
        title = 'label:%d,pred:%d' % (labels[i], preds[i])
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

crear modelo

model = tf.keras.models.Sequential()

añadir capa

model.add(tf.keras.layers.Flatten(input_shape=(28,28)))
model.add(tf.keras.layers.Dense(units=256,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=64,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=32,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=10,\
          kernel_initializer='normal', activation='softmax'))

Resumen Modelo

model.summary()


modo de entrenamiento

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

modelo de entrenamiento

#学习率自动调节,输出进度条日志
start_time = time()
history = model.fit(x_train, y_train,\
                    validation_split=0.2, epochs=10, batch_size=1000,\
                    verbose=1)
end_time = time()
print('用时%.1fs' % (end_time-start_time))

history.history: datos de tipo diccionario, incluidos pérdida, 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')

inserte la descripción de la imagen aquí
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))

El tiempo de entrenamiento con keras es más corto y la precisión del modelo también tiene margen de mejora.

modelo de predicción

#分类预测
preds = model.predict_classes(x_test)
show(x_test.numpy(), y_test, preds)

inserte la descripción de la imagen aquí


Resumir

Una capa de red neuronal incluye múltiples neuronas, la dimensión de datos de entrada corresponde a la primera dimensión del peso de la capa oculta, el número de neuronas corresponde a la segunda dimensión del peso de la capa oculta y la capa de salida convierte la salida de la capa oculta en la dimensión del valor predicho.
Cuando se guarda y carga el modelo, puede haber casos en los que el nombre del peso no corresponda, y el peso se puede imprimir para compararlo y modificarlo.
Al definir la clase de capa completamente conectada, se pueden omitir las operaciones repetidas de definir una red neuronal multicapa.La red multicapa tiene muchos parámetros, lleva mucho tiempo entrenarla y tiene una mayor capacidad para expresar el modelo, pero la tasa de precisión no es necesariamente más alta Ajuste los parámetros de entrenamiento apropiadamente.
El uso de keras puede definir fácilmente el modelo, realizar entrenamiento y evaluación, y puede realizar operaciones como la transformación de dimensiones y la codificación one-hot internamente, y el tiempo de entrenamiento también es corto.

Supongo que te gusta

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