Cómo cambiar un modelo de clasificación binaria a un modelo de clasificación múltiple
En este caso, se utiliza el marco de aprendizaje profundo MindSpore.Con sus módulos de paquete amigables, definición de estructura de modelo, definición de función de pérdida, implementación de descenso de gradiente y otros procesos, el entrenamiento de modelo se puede realizar con llamadas de función simples, lo que mejora en gran medida la eficiencia del modelo. desarrollo eficiencia
1. Cargue el conjunto de datos
Cargue el conjunto de datos completo de diez categorías
import os
import numpy as np
import moxing as mox
import mindspore.dataset as ds
datasets_dir = '../datasets'
if not os.path.exists(datasets_dir):
os.makedirs(datasets_dir)
if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip',
os.path.join(datasets_dir, 'MNIST_Data.zip'))
os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
# 读取完整训练样本和测试样本
mnist_ds_train = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/train"))
mnist_ds_test = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/test"))
train_len = mnist_ds_train.get_dataset_size()
test_len = mnist_ds_test.get_dataset_size()
print('训练集规模:', train_len, ',测试集规模:', test_len)
Tamaño del conjunto de entrenamiento: 60000, tamaño del conjunto de prueba: 10000
ver 10 muestras
from PIL import Image
items_train = mnist_ds_train.create_dict_iterator(output_numpy=True)
train_data = np.array([i for i in items_train])
images_train = np.array([i["image"] for i in train_data])
labels_train = np.array([i["label"] for i in train_data])
batch_size = 10 # 查看10个样本
batch_label = [lab for lab in labels_train[:10]]
print(batch_label)
batch_img = images_train[0].reshape(28, 28)
for i in range(1, batch_size):
batch_img = np.hstack((batch_img, images_train[i].reshape(28, 28))) # 将一批图片水平拼接起来,方便下一步进行显示
Image.fromarray(batch_img)
[0, 2, 2, 7, 8, 4, 9, 1, 8, 8]
2. Procesar el conjunto de datos
Los conjuntos de datos son muy importantes para el entrenamiento. Un buen conjunto de datos puede mejorar efectivamente la precisión y la eficiencia del entrenamiento. Antes de usar el conjunto de datos, generalmente se realiza algún procesamiento en el conjunto de datos.
Realizar operaciones de aumento de datos
import mindspore.dataset.vision.c_transforms as CV
import mindspore.dataset.transforms.c_transforms as C
from mindspore.dataset.vision import Inter
from mindspore import dtype as mstype
num_parallel_workers = 1
resize_height, resize_width = 28, 28
# according to the parameters, generate the corresponding data enhancement method
resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) # 对图像数据像素进行缩放
type_cast_op = C.TypeCast(mstype.int32) # 将数据类型转化为int32。
hwc2chw_op = CV.HWC2CHW() # 对图像数据张量进行变换,张量形式由高x宽x通道(HWC)变为通道x高x宽(CHW),方便进行数据训练。
# using map to apply operations to a dataset
mnist_ds_train = mnist_ds_train.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers)
mnist_ds_train = mnist_ds_train.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)
mnist_ds_train = mnist_ds_train.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers)
buffer_size = 10000
mnist_ds_train = mnist_ds_train.shuffle(buffer_size=buffer_size) # 打乱训练集的顺序
Realizar la normalización de datos
Estandarice y normalice los datos de la imagen para que el valor de cada píxel esté en el rango de (0,1), lo que puede mejorar la eficiencia del entrenamiento.
rescale = 1.0 / 255.0
shift = 0.0
rescale_nml = 1 / 0.3081
shift_nml = -1 * 0.1307 / 0.3081
rescale_op = CV.Rescale(rescale, shift)
mnist_ds_train = mnist_ds_train.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers)
rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
mnist_ds_train = mnist_ds_train.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers)
mnist_ds_train = mnist_ds_train.batch(60000, drop_remainder=True) # 对数据集进行分批,此处加载完整的训练集
3. Encapsular en una función
En este punto, hemos completado la preparación de los datos de entrenamiento, y las operaciones anteriores se pueden encapsular en la función load_data_all y la función process_dataset, para que puedan usarse nuevamente más tarde.
Definir operaciones de procesamiento de datos.
Defina una función process_dataset para realizar operaciones de mejora y procesamiento de datos:
-
Defina algunos parámetros necesarios para el aumento y procesamiento de datos.
-
De acuerdo con los parámetros, generar la operación de aumento de datos correspondiente.
-
Aplique operaciones de datos a conjuntos de datos usando la función de mapeo de mapas.
-
Procese el conjunto de datos generado.
%%writefile ../datasets/MNIST_Data/process_dataset.py
def process_dataset(mnist_ds, batch_size=32, resize= 28, repeat_size=1,
num_parallel_workers=1):
"""
process_dataset for train or test
Args:
mnist_ds (str): MnistData path
batch_size (int): The number of data records in each group
resize (int): Scale image data pixels
repeat_size (int): The number of replicated data records
num_parallel_workers (int): The number of parallel workers
"""
import mindspore.dataset.vision.c_transforms as CV
import mindspore.dataset.transforms.c_transforms as C
from mindspore.dataset.vision import Inter
from mindspore import dtype as mstype
# define some parameters needed for data enhancement and rough justification
resize_height, resize_width = resize, resize
rescale = 1.0 / 255.0
shift = 0.0
rescale_nml = 1 / 0.3081
shift_nml = -1 * 0.1307 / 0.3081
# according to the parameters, generate the corresponding data enhancement method
resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)
rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)
rescale_op = CV.Rescale(rescale, shift)
hwc2chw_op = CV.HWC2CHW()
type_cast_op = C.TypeCast(mstype.int32)
c_trans = [resize_op, rescale_op, rescale_nml_op, hwc2chw_op]
# using map to apply operations to a dataset
mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)
mnist_ds = mnist_ds.map(operations=c_trans, input_columns="image", num_parallel_workers=num_parallel_workers)
# process the generated dataset
buffer_size = 10000
mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)
mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)
mnist_ds = mnist_ds.repeat(repeat_size)
return mnist_ds
Definir la función de carga de datos
%%writefile ../datasets/MNIST_Data/load_data_all.py
def load_data_all(datasets_dir):
import os
if not os.path.exists(datasets_dir):
os.makedirs(datasets_dir)
import moxing as mox
if not os.path.exists(os.path.join(datasets_dir, 'MNIST_Data.zip')):
mox.file.copy('obs://modelarts-labs-bj4-v2/course/hwc_edu/python_module_framework/datasets/mindspore_data/MNIST_Data.zip',
os.path.join(datasets_dir, 'MNIST_Data.zip'))
os.system('cd %s; unzip MNIST_Data.zip' % (datasets_dir))
# 读取完整训练样本和测试样本
import mindspore.dataset as ds
datasets_dir = '../datasets'
mnist_ds_train = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/train"))
mnist_ds_test = ds.MnistDataset(os.path.join(datasets_dir, "MNIST_Data/test"))
train_len = mnist_ds_train.get_dataset_size()
test_len = mnist_ds_test.get_dataset_size()
print('训练集规模:', train_len, ',测试集规模:', test_len)
return mnist_ds_train, mnist_ds_test, train_len, test_len
4. Cargue el conjunto de prueba procesado
import os, sys
sys.path.insert(0, os.path.join(os.getcwd(), '../datasets/MNIST_Data'))
from process_dataset import process_dataset
mnist_ds_test = process_dataset(mnist_ds_test, batch_size= 10000)
5. Definir la estructura de la red y la función de evaluación
import mindspore
import mindspore.nn as nn
import mindspore.ops as ops
from mindspore.common.initializer import Normal
class Network(nn.Cell):
def __init__(self, num_of_weights):
super(Network, self).__init__()
self.fc = nn.Dense(in_channels=num_of_weights, out_channels=10, weight_init=Normal(0.02)) # 定义一个全连接层
self.nonlinearity = nn.Sigmoid()
self.flatten = nn.Flatten()
def construct(self, x): # 加权求和单元和非线性函数单元通过定义计算过程来实现
x = self.flatten(x)
z = self.fc(x)
pred_y = self.nonlinearity(z)
return pred_y
def evaluate(pred_y, true_y):
pred_labels = ops.Argmax(output_type=mindspore.int32)(pred_y)
correct_num = (pred_labels == true_y).asnumpy().sum().item()
return correct_num
6. Definir la función de pérdida de entropía cruzada y el optimizador
# 损失函数
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
# 创建网络
network = Network(28*28)
lr = 0.01
momentum = 0.9
# 优化器
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)
7. Implementar la función de formación
def train(network, mnist_ds_train, max_epochs= 50):
net = WithLossCell(network, net_loss)
net = TrainOneStepCell(net, net_opt)
network.set_train()
for epoch in range(1, max_epochs + 1):
train_correct_num = 0.0
test_correct_num = 0.0
for inputs_train in mnist_ds_train:
output = net(*inputs_train)
train_x = inputs_train[0]
train_y = inputs_train[1]
pred_y_train = network.construct(train_x) # 前向传播
train_correct_num += evaluate(pred_y_train, train_y)
train_acc = float(train_correct_num) / train_len
for inputs_test in mnist_ds_test:
test_x = inputs_test[0]
test_y = inputs_test[1]
pred_y_test = network.construct(test_x)
test_correct_num += evaluate(pred_y_test, test_y)
test_acc = float(test_correct_num) / test_len
if (epoch == 1) or (epoch % 10 == 0):
print("epoch: {0}/{1}, train_losses: {2:.4f}, tain_acc: {3:.4f}, test_acc: {4:.4f}" \
.format(epoch, max_epochs, output.asnumpy(), train_acc, test_acc, cflush=True))
8. Configurar la información de ejecución
Antes de la capacitación formal, use context.set_context para configurar la información necesaria para la ejecución, como el modo de ejecución, la información de back-end, el hardware y otra información.
from mindspore import context
context.set_context(mode=context.GRAPH_MODE, device_target="CPU") # device_target 可选 CPU/GPU, 当选择GPU时mindspore规格也需要切换到GPU
9. Empieza a entrenar
import time
from mindspore.nn import WithLossCell, TrainOneStepCell
max_epochs = 100
start_time = time.time()
print("*"*10 + "开始训练" + "*"*10)
train(network, mnist_ds_train, max_epochs= max_epochs)
print("*"*10 + "训练完成" + "*"*10)
cost_time = round(time.time() - start_time, 1)
print("训练总耗时: %.1f s" % cost_time)
**********开始训练*********** época: 1/100, train_losses: 2.2832, tain_acc: 0.1698, test_acc: 0.1626 época: 10/100, train_losses: 2.0465, tain_acc : 0.6343, test_acc: 0.6017 época: 20/100, train_losses: 1.8368, tain_acc: 0.7918, test_acc: 0.7812 época: 30/100, train_losses: 1.7602, tain_acc: 0.8138, test_acc: 0. 8017 época: 40/100, tren_pérdidas: 1.7245, tain_acc: 0.8238, test_acc: 0.7972 época: 50/100, train_losses: 1.7051, tain_acc: 0.8337, test_acc: 0.8044 época: 60/100, train_losses: 1.6922, tain_acc: 0.8403, test_acc : 0.8047 época: 70/100 , tren_pérdidas: 1.6827 , tain_acc: 0.8454, test_acc: 0.8033 época: 80/100, train_losses: 1.6752, tain_acc: 0.8501, test_acc: 0.8051 época: 90/100, train_losses: 1,6689, tain_acc: 0,8536, test_acc: 0,8049 época: 100/100, train_losses: 1,6635, tain_acc: 0,8569, test_acc: 0,8037 *********** entrenamiento completo*** * **** Tiempo total de entrenamiento: 430,7 s
Hasta ahora, con una pequeña cantidad de modificación del código basada en la clasificación binaria de dígitos escritos a mano, el reconocimiento de diez clases de dígitos escritos a mano se ha realizado rápidamente.
El proceso de modificación es muy simple, pero como se puede ver en los resultados anteriores, el modelo entrenó durante 100 épocas y solo alcanzó un 80 % de precisión en la tarea de reconocimiento de dígitos escritos a mano, mientras que en la sección anterior, la tarea de dos categorías En la práctica , el modelo entrenado durante 50 épocas logró una tasa de precisión del 99 %, lo que indica que en un modelo simple como un perceptrón, el reconocimiento de dígitos escritos a mano es más difícil que la clasificación binaria.