"Introducción al aprendizaje profundo" Capítulo 4 Combate real: Reconocimiento de números escritos a mano


prefacio

Este artículo completa el pequeño caso de reconocimiento de dígitos escritos a mano basado en el contenido del Capítulo 4 de "Introducción al Aprendizaje Profundo". El enfoque de este capítulo es cómo dejar que la red neuronal " aprenda a aprender ". Para permitir que la red neuronal aprenda a aprender, 损失函数este indicador se importará para encontrar los parámetros de peso que minimicen la función de pérdida. Para encontrar el valor más pequeño posible de la función de pérdida, usamos 梯度下降法.


1. Conocimiento teórico

(1) Pasos de aprendizaje de la red neuronal

  1. mini-lote : seleccione aleatoriamente una parte de los datos de los datos de entrenamiento, esta parte de los datos se llama mini-lote. Envíe los datos en el mini lote a la red y luego podrá obtener el resultado de la predicción. Según el resultado previsto y el resultado correcto, se calcula la función de pérdida.
  2. Calcular el gradiente : Para reducir el valor de la función de pérdida de mini-lote, se debe calcular el gradiente de cada parámetro de peso. El gradiente representa la dirección en la que el valor de la función de pérdida disminuye más.
  3. Parámetros de actualización : los parámetros de peso se actualizan ligeramente a lo largo de la dirección del gradiente.
  4. Repetir : Repita los pasos 1-3.

(2) Gradiente y descenso de gradiente

Gradiente : El vector sumado por las derivadas parciales de todas las variables se llama gradiente. La dirección indicada por el gradiente es la dirección en la que el valor de la función decrece más en cada punto.
Método de gradiente : Un método que avanza continuamente a lo largo de la dirección del gradiente y reduce gradualmente el valor de la función. Entre ellos, el método de ascenso de gradiente se refiere al método de gradiente para encontrar el valor máximo; el método de descenso de gradiente se refiere al método de gradiente para encontrar el valor mínimo.

(3) función de pérdida

Función de pérdida : el indicador utilizado en el aprendizaje de la red neuronal se puede utilizar para indicar hasta qué punto la red neuronal actual no se ajusta a los datos supervisados. Las funciones de pérdida comúnmente utilizadas son el error cuadrático medio y el error de entropía cruzada.
均方误差:
inserte la descripción de la imagen aquí
donde y_k representa la salida de la red neuronal, t_k representa los datos reales y k representa la dimensionalidad de los datos.
Código:

def mean_squared_error(y, t):
	return 0.5 * np.sum((y-t)**2)

交叉熵误差:
inserte la descripción de la imagen aquí
y_k representa la salida de la red neuronal (es una probabilidad, como la salida de sigmoid o softmax), t_k es la etiqueta de la solución correcta (t_k está representada por one-hot) implementación del código
:

def cross_entropy_error(y, t):
	delta = 1e-7
	return -np.sum(t * np.log(y + delta))

(四) época, número de litros

Época : la época es una unidad, y una época representa la cantidad de actualizaciones cuando todos los datos de entrenamiento en el aprendizaje se han usado una vez . Para 10.000 datos de entrenamiento, cuando se aprende con un mini lote de 100 datos, repita el método de descenso de gradiente estocástico 100 veces y se habrán visto todos los datos de entrenamiento. Entonces, en este ejemplo, la época es 100.
iters_num : el número de iteraciones del método de gradiente. (En este caso de reconocimiento de dígitos escritos a mano, iters_num es 10000. Significa que cada vez que se selecciona aleatoriamente un mini_lote, la extracción se repite 10000 veces).

(5) La estructura de la red neuronal de este caso

Esta red utiliza una red neuronal de dos capas. La estructura de la red es más o menos la siguiente:

Capa de entrada: 784 neuronas.
Capa oculta: 50 neuronas.
Capa de salida: 10 neuronas.


2. Todos los códigos

import sys, os

sys.path.append(os.pardir)
import numpy as np
import matplotlib.pyplot as plt
from common.functions import *
from common.gradient import numerical_gradient
from dataset.mnist import load_mnist
from dataset.two_layer_net import TwoLayerNet


def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        batch_size = y.shape[0]
        return -np.sum(t * np.log(y + 1e-7)) / batch_size


class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 初始化权重
        self.params = {
    
    }
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    def sigmoid(a):
        return 1 / (1 + np.exp(-a))

    def softmax(a):
        exp_a = np.exp(a)
        sum = np.sum(exp_a)
        y = exp_a / sum
        return y

    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        a1 = np.dot(x, W1) + b1
        z1 = self.sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        z2 = self.softmax(a2)
        return z2

    # x是输入数据,t是标签
    def loss(self, x, t):
        y = self.predict(x)
        return cross_entropy_error(y, t)  # 交叉熵损失函数

    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy

    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        grads = {
    
    }
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        return grads

    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
    train_loss_list = []
    train_acc_list = []
    test_acc_list = []


    # 超参数
    iters_num = 500
    train_size = x_train.shape[0]
    batch_size = 100
    learning_rate = 0.1
    network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
    # 平均每个epoch的重复次数
    iter_per_epoch = max(train_size / batch_size, 1)
    for i in range(iters_num):
        # 获取mini-batch
        batch_mask = np.random.choice(train_size, batch_size)
        x_batch = x_train[batch_mask]
        t_batch = t_train[batch_mask]

        # 计算梯度
        grad = network.numerical_gradient(x_batch, t_batch)
        print('hello')
        # 更新参数
        for key in ('W1', 'b1', 'W2', 'b2'):
            network.params[key] -= learning_rate * grad[key]

        # 记录学习过程
        loss = network.loss(x_batch, t_batch)
        train_loss_list.append(loss)

        # 计算每个epoch的识别精度
        if i % iter_per_epoch == 0:
            train_acc = network.accuracy(x_train, t_train)
            test_acc = network.accuracy(x_test, t_test)
            train_acc_list.append(train_acc)
            test_acc_list.append(test_acc)


    # 导入数据
    m = list(np.arange(1, iters_num+1))
    n = list(np.arange(1, len(train_acc_list)+1))
    t = list(np.arange(1, len(test_acc_list)+1))
    # 绘图命令
    print(train_loss_list)
    print(train_acc_list)
    print(test_acc_list)
    # 画第一个图
    plt.subplot(221)
    plt.plot(m, train_loss_list)
    # show出图形
    plt.show()

Ejecución de resultados:
(La abscisa en la siguiente figura es iters_num, y la ordenada es el valor de la función de pérdida)
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/rellvera/article/details/127933046
Recomendado
Clasificación