import mindspore
# 载入mindspore的默认数据集
import mindspore.dataset as ds
# 常用转化用算子
import mindspore.dataset.transforms.c_transforms as C
# 图像转化用算子
####____####
import mindspore.dataset.vision.c_transforms as CV
from mindspore.common import dtype as mstype
# mindspore的tensor
from mindspore import Tensor
# 各类网络层都在nn里面
import mindspore.nn as nn
# 参数初始化的方式
from mindspore.common.initializer import TruncatedNormal
# 设置mindspore运行的环境
from mindspore import context
# 引入训练时候会使用到回调函数,如checkpoint, lossMoniter
from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor
# 引入模型
from mindspore.train import Model
# 引入评估模型的包
from mindspore.nn.metrics import Accuracy
# numpy
import numpy as np
# 画图用
import matplotlib.pyplot as plt
import mindspore.nn as nn
####____####
# 下载数据相关的包
import os
import requests
import zipfile
#创建图像标签列表
#定义一个将数字标签映射到类名的字典,用于图像标注
category_dict = {0:'airplane',1:'automobile',2:'bird',3:'cat',4:'deer',5:'dog',
6:'frog',7:'horse',8:'ship',9:'truck'}# 键: CIFAR-10数据集中的标签索引值(0-9),值: 对应的类别名称
####____####
current_path = os.getcwd()#获取当前工作目录路径
#构建CIFAR-10测试数据集路径
data_path = os.path.join(current_path, 'data/10-verify-bin')#拼接当前路径与数据子目录(测试集)
#创建测试数据集对象
cifar_ds = ds.Cifar10Dataset(data_path)#使用ds.Cifar10Dataset类从指定路径加载CIFAR-10测试集
# 设置图像大小
plt.figure(figsize=(8,8))
i = 1#初始化计数器变量,用于追踪当前显示的图像索引
# 打印9张子图
for dic in cifar_ds.create_dict_iterator():#创建数据迭代器,每次迭代返回包含图像和标签的字典
plt.subplot(3,3,i)
####____####
plt.imshow(dic['image'].asnumpy())
plt.xticks([])
plt.yticks([])
plt.axis('off')
plt.title(category_dict[dic['label'].asnumpy().sum()])
i +=1
if i > 9 :
break
plt.show()
cifar_ds=ds.Cifar10Dataset(data_path)
def get_data(datapath):
cifar_ds = ds.Cifar10Dataset(datapath)#原始数据集对象
return cifar_ds
def get_data(datapath):
cifar_ds = ds.Cifar10Dataset(datapath)#原始数据集对象
return cifar_ds
def process_dataset(cifar_ds,batch_size =32,status="train"):
#batch_size: 批处理大小 (默认32);status: 数据集类型,"train"表示训练集,其他表示测试集/验证集
'''
---- 定义算子 ----
'''
# 归一化缩放因子
rescale = 1.0 / 255.0
# 像素值平移量
shift = 0.0
resize_op = CV.Resize((32, 32))#将所有图像调整到32*32尺寸
rescale_op = CV.Rescale(rescale, shift)#对图像进行归一化缩放(*rescale,+shift)
# 对于RGB三通道分别设定mean和std
normalize_op = CV.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
if status == "train":
# 随机裁剪
random_crop_op = CV.RandomCrop([32, 32], [4, 4, 4, 4])
# 随机翻转
random_horizontal_op = CV.RandomHorizontalFlip()
# 通道变化
channel_swap_op = CV.HWC2CHW()
# 类型变化
typecast_op = C.TypeCast(mstype.int32)
'''
---- 算子运算 ----
'''
cifar_ds = cifar_ds.map(input_columns="label", operations=typecast_op)#讲标签列转换为int32类型
if status == "train":
cifar_ds = cifar_ds.map(input_columns="image", operations=random_crop_op)#应用随即裁剪增强
cifar_ds = cifar_ds.map(input_columns="image", operations=random_horizontal_op)#应用随机水平翻转增强
cifar_ds = cifar_ds.map(input_columns="image", operations=resize_op)#应用图像大小调整
cifar_ds = cifar_ds.map(input_columns="image", operations=rescale_op)#应用缩放操作
cifar_ds = cifar_ds.map(input_columns="image", operations=normalize_op)#应用标准化
cifar_ds = cifar_ds.map(input_columns="image", operations=channel_swap_op)#应用通道转换
# shuffle
cifar_ds = cifar_ds.shuffle(buffer_size=1000)#使用大小为1000的缓冲区对数据进行随机混洗
# 切分数据集到batch_size
cifar_ds = cifar_ds.batch(batch_size, drop_remainder=True)#将数据集按照批次大小分组,并丢弃最后一个不完整的批次
return cifar_ds#返回处理后的数据集
data_path = os.path.join(current_path, 'data/10-batches-bin')#拼接当前路径与子路径‘data/1-...’,形成完整数据集路径
batch_size=32#批处理大小
status="train"#设置当前数据集为训练集
# 生成训练数据集
cifar_ds = get_data(data_path)#获取CIFAR-10数据集的原始train对象
ds_train = process_dataset(cifar_ds,batch_size =batch_size, status=status)#调用process_dataset函数对原始数据集进行预处理
class BasicBlock(nn.Cell):
"""基本残差块"""
expansion = 1
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, pad_mode='pad', has_bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, pad_mode='pad', has_bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.downsample = downsample
def construct(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity # 残差连接
out = self.relu(out)
return out
class ResNet(nn.Cell):
"""完整的ResNet网络"""
def __init__(self, block, layers, num_classes=10):
super(ResNet, self).__init__()
self.in_channels = 64
self.conv = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, pad_mode='pad', has_bias=False)
self.bn = nn.BatchNorm2d(64)
self.relu = nn.ReLU()
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2) # 去掉padding参数
self.layer1 = self._make_layer(block, 64, layers[0])
self.layer2 = self._make_layer(block, 128, layers[1], 2)
self.layer3 = self._make_layer(block, 256, layers[2], 2)
self.layer4 = self._make_layer(block, 512, layers[3], 2)
self.avgpool = nn.AvgPool2d(kernel_size=8, stride=1) # 使用AvgPool2d代替AdaptiveAvgPool2d
self.fc = nn.Dense(512 * block.expansion, num_classes)
def _make_layer(self, block, out_channels, blocks, stride=1):
downsample = None
if stride != 1 or self.in_channels != out_channels * block.expansion:
downsample = nn.SequentialCell([
nn.Conv2d(self.in_channels, out_channels * block.expansion, kernel_size=1, stride=stride, has_bias=False),
nn.BatchNorm2d(out_channels * block.expansion),
])
layers = []
layers.append(block(self.in_channels, out_channels, stride, downsample))
self.in_channels = out_channels * block.expansion
for _ in range(1, blocks):
layers.append(block(self.in_channels, out_channels))
return nn.SequentialCell(layers)
def construct(self, x):
x = self.conv(x)
x = self.bn(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.shape[0], -1)
x = self.fc(x)
return x
# 创建ResNet模型
network = ResNet(BasicBlock, [2, 2, 2, 2]) # ResNet18
# 返回当前设备
device_target = mindspore.context.get_context('device_target')
# 确定图模型是否下沉到芯片上
dataset_sink_mode = True if device_target in ['Ascend','GPU'] else False
# 设置模型的设备与图的模式
context.set_context(mode=context.GRAPH_MODE, device_target=device_target)
# 使用交叉熵函数作为损失函数
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")
# 优化器为Adam
net_opt = nn.Adam(params=network.trainable_params(), learning_rate=0.001)
# 监控每个epoch训练的时间
time_cb = TimeMonitor(data_size=ds_train.get_dataset_size())
from mindspore.train.callback import Callback#导入callback基类,用于创建自定义回调函数
class EvalCallBack(Callback):#自定义评估回调类,继承自callback基类
def __init__(self, model, eval_dataset, eval_per_epoch, epoch_per_eval):#初始化方法
self.model = model#训练好的模型,用于评估
self.eval_dataset = eval_dataset#评估数据集
self.eval_per_epoch = eval_per_epoch#评估频率
self.epoch_per_eval = epoch_per_eval#字典,用于保存评估历史
def epoch_end(self, run_context):
cb_param = run_context.original_args()#获取运行上下文参数
cur_epoch = cb_param.cur_epoch_num#提取当前epoch序号
if cur_epoch % self.eval_per_epoch == 0:#检查是否到达评估点
acc = self.model.eval(self.eval_dataset, dataset_sink_mode=False)#评估模型性能
self.epoch_per_eval["epoch"].append(cur_epoch)
self.epoch_per_eval["acc"].append(acc["Accuracy"])
print(acc)
# 设置CheckpointConfig,callback函数。save_checkpoint_steps=训练总数/batch_size
config_ck = CheckpointConfig(save_checkpoint_steps=1562,
keep_checkpoint_max=10)
ckpoint_cb = ModelCheckpoint(prefix="checkpoint_lenet_original", directory='./results',config=config_ck)#创建模型jian'cha'dii'an
# 建立可训练模型
model = Model(network = network, loss_fn=net_loss,optimizer=net_opt, metrics={"Accuracy": Accuracy()})
eval_per_epoch = 1
epoch_per_eval = {"epoch": [], "acc": []}
eval_cb = EvalCallBack(model, ds_train, eval_per_epoch, epoch_per_eval)
print("============== Starting Training ==============")
model.train(100, ds_train,callbacks=[ckpoint_cb, LossMonitor(per_print_times=1),eval_cb],dataset_sink_mode=dataset_sink_mode)
data_path = os.path.join(current_path, 'data/10-verify-bin')
batch_size=32
status="test"
# 生成测试数据集
cifar_ds = ds.Cifar10Dataset(data_path)
ds_eval = process_dataset(cifar_ds,batch_size=batch_size,status=status)
res = model.eval(ds_eval, dataset_sink_mode=dataset_sink_mode)
# 评估测试集
print('test results:',res)
#创建图像标签列表
category_dict = {0:'airplane',1:'automobile',2:'bird',3:'cat',4:'deer',5:'dog',
6:'frog',7:'horse',8:'ship',9:'truck'}
cifar_ds = get_data('./data/10-verify-bin')
df_test = process_dataset(cifar_ds,batch_size=1,status='test')
def normalization(data):
_range = np.max(data) - np.min(data)
return (data - np.min(data)) / _range
# 设置图像大小
plt.figure(figsize=(10,10))
i = 1
# 打印9张子图
for dic in df_test:
# 预测单张图片
input_img = dic[0]
output = model.predict(Tensor(input_img))
output = nn.Softmax()(output)
# 反馈可能性最大的类别
predicted = np.argmax(output.asnumpy(),axis=1)[0]
# 可视化
plt.subplot(3,3,i)
# 删除batch维度
input_image = np.squeeze(input_img.asnumpy(),axis=0).transpose(1,2,0)
# 重新归一化,方便可视化
input_image = normalization(input_image)
plt.imshow(input_image)
plt.xticks([])
plt.yticks([])
plt.axis('off')
plt.title('True label:%s,\n Predicted:%s'%(category_dict[dic[1].asnumpy().sum()],category_dict[predicted]))
i +=1
if i > 9 :
break
plt.show()
修改以上代码,保留代码的框架和基本逻辑,把神经网络算法从lenet的网络结构改变为ResNet网络(尽量少的改动代码),给出修改后的完整代码,要求在上代码测试集准确率73%的基础上进一步提升准确率,预期提升到95%以上
其他要求:
1、按照jupyter notebook文件即.ipynb文件的样式,完成作业;
2、作业要求注释风格良好,代码风格良好,保留中间运行结果;(作业成绩好坏评定的依据)
3、在华为云modelarts GPU服务器上运行;
最新发布