切分init_net

本文介绍如何解析Caffe2的二进制模型,包括init_net和predict_net,通过自定义Python脚本实现对特定层的读取与保存。文章详细解释了proto消息的使用,以及如何通过NetDef结构读取并处理模型数据。

备注:原始的init加密过,不能直接使用,因此只能从源头寻找weights。幸运的是所有init_net和predict_net都采用了一种名叫proto的组织方式,所有我们学习一下proto.

'''
procedure
1. input the binary data and use the X_pd2.py to parse the binary data
2. save the structure and the parameters of each operator in a binary file.
3. read the produced binary file and test whether it is the same with the origianl binary file.
4. depend on the principle of partition to save the binary file.
'''
from caffe2.proto import caffe2_pb2 # it has the definition of message NetDef
import os
import sys
#1. 把控制台输出的内容写到特定文件里。

sys.stdout = open("mult-ops.txt", "w") 
CAFFE_MODELS = "/home/wujing/software/software/lib/python2.7/site-packages/caffe2/python/models"
MODEL = ['squeezenet', 'init_net.pb', 'predict_net.pb']

INIT_NET = os.path.join(CAFFE_MODELS, MODEL[0], MODEL[1])

#2.从NefDef中读取内容

PS: init_net和predict_net是用特定格式存储的二进制文件(X.pb),这些格式信息(称为Message)存储在了caffe2_pb2.py文件里。这个文件里有多种Message,init和predict与NetDef对应,下图是NefDef(简称ND)的结构信息。ND中有一个核心要素op,op本身也是一种Message,结构与ND类似。


#3. 核心操作

函数readOpList是拆分的核心步骤。上方右图是init_net转成明文后的结果,init_net由多个op构成,每个op都对应OperatorDef结果。因此,我们可以仿造init_net的结构特征定,制化我们的init_文件。具体过程如下:

def readOpList(init_netdef,num_layers):
   i = 0
   opslist = caffe2_pb2.NetDef()
#1.生成最外成的NetDef来承载内部的ops。
   for ops in init_netdef.op:#2.迭代init
      if i< num_layers:
         temp = opslist.op.add()
#3.向NetDef添加内容,只能先用一个变量承接.add()的调用结果,不能讲ops传入add()中
         temp.CopyFrom(ops)#4.将ops的内容复制到temp中,不能写成temp = ops,否者生成的定制文件格式是:op{} op{}。
      else:
         break
      i = i+1
   #print(opslist)# print可以在控制台输出oplist的明文
   result = opslist.SerializeToString()
#转化成二进制序列,注意:调用STS方法会直接转化oplist,函数返回结果是一个指针,不是有效的二进制序列。 这里一定要用result来承接序列化后的结果。
   return result
      
#1. read the binary data and put them into oplist
   
'''
1-1 import caffe2_pb2, it contains the definition of message NetDef which define
the structure of ops.
1-2 read the binary data of init_net into oplist
'''

#4.读取init_net文件

先创建一个对象,然后填入内容
oplist = caffe2_pb2.NetDef() #创建对象
with open(INIT_NET,"rb") as f:
   temp = f.read()
   oplist.ParseFromString(temp)#填入内容
   f.close()

#2. read the basic unit OperatorDef which is serialized as a string
result = readOpList(oplist)#获取二进制结果

#3. store the result of step 2 into a binary file
#DEST_FILE = "/home/wujing/matieral/project/test_prop/first_op.pb"
DEST_FILE = "/home/wujing/matieral/project/test_prop/string_res.txt"

#5.输入二进制结果

先判断是否存在目标文件,如果不存在,创建对应的文件;如果存在,写入内容。

if not os.path.exists(DEST_FILE):
   with open(DEST_FILE,'w+') as f:
      f.write('')
      f.close()   
with open(DEST_FILE,"wb") as f:
   f.write(result)
   f.close()

import torch import torch.nn as nn from torch.autograd import grad import numpy as np import os from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score device = 'cuda' if torch.cuda.is_available() else 'cpu' # ================= 工具函数 ================= class AverageMeter(object): def __init__(self): self.reset() def reset(self): self.val = 0; self.avg = 0; self.sum = 0; self.count = 0 def update(self, val, n=1): self.val = val; self.sum += val * n; self.count += n; self.avg = self.sum / self.count def calculate_metrics(y_true, y_pred): """计算 MAE, MSE, RMSE, R2""" y_true = np.array(y_true).flatten() y_pred = np.array(y_pred).flatten() mae = mean_absolute_error(y_true, y_pred) mse = mean_squared_error(y_true, y_pred) rmse = np.sqrt(mse) r2 = r2_score(y_true, y_pred) return mae, mse, rmse, r2 # ================= 基础层 ================= class Sin(nn.Module): def forward(self, x): return torch.sin(x) class MLP(nn.Module): def __init__(self, input_dim, output_dim, layers_num=4, hidden_dim=50, dropout=0.0): super(MLP, self).__init__() self.layers = [] for i in range(layers_num): in_d = input_dim if i == 0 else hidden_dim out_d = output_dim if i == layers_num - 1 else hidden_dim self.layers.append(nn.Linear(in_d, out_d)) if i < layers_num - 1: self.layers.append(Sin()) if dropout > 0: self.layers.append(nn.Dropout(p=dropout)) self.net = nn.Sequential(*self.layers) self._init_weights() def _init_weights(self): for layer in self.net: if isinstance(layer, nn.Linear): nn.init.xavier_normal_(layer.weight) def forward(self, x): return self.net(x) # ================= 注意力融合模块 ================= class CrossAttentionFusion(nn.Module): def __init__(self, feature_dim=32, num_heads=2, dropout=0.1): super().__init__() self.attn = nn.MultiheadAttention(embed_dim=feature_dim, num_heads=num_heads, batch_first=True, dropout=dropout) self.norm = nn.LayerNorm(feature_dim) self.dropout = nn.Dropout(dropout) # 可学习门控 self.gate_net = nn.Sequential( nn.Linear(feature_dim * 2, feature_dim), nn.Tanh(), nn.Linear(feature_dim, feature_dim), nn.Sigmoid() ) def forward(self, curr_feature, hist_feature): # Query: [B, 1, D], Key/Val: [B, Seq, D] query = curr_feature.unsqueeze(1) attn_out, attn_weights = self.attn(query, hist_feature, hist_feature) attn_out = self.dropout(attn_out.squeeze(1)) # 门控融合 combined = torch.cat([curr_feature, attn_out], dim=1) gate = self.gate_net(combined) out = self.norm(curr_feature + gate * attn_out) return out, attn_weights # ================= 预测网络 U (增强版) ================= class Solution_u_Enhanced(nn.Module): def __init__(self, input_dim=17, hidden_dim=60, feature_dim=32): super(Solution_u_Enhanced, self).__init__() # 假设 input_dim 是 17 (xt特征) self.curr_encoder = MLP(input_dim, feature_dim, layers_num=3, hidden_dim=hidden_dim) self.hist_encoder = MLP(input_dim, feature_dim, layers_num=3, hidden_dim=hidden_dim) self.fusion = CrossAttentionFusion(feature_dim=feature_dim) self.predictor = nn.Sequential( nn.Linear(feature_dim, hidden_dim), Sin(), nn.Linear(hidden_dim, 1) ) def forward(self, xt, history_data=None): curr_feat = self.curr_encoder(xt) attn_weights = None if history_data is not None: # history: [B, Seq, 17] b, s, d = history_data.shape hist_feat = self.hist_encoder(history_data.reshape(-1, d)).reshape(b, s, -1) fused_feat, attn_weights = self.fusion(curr_feat, hist_feat) out = self.predictor(fused_feat) else: out = self.predictor(curr_feat) return out, attn_weights # ================= 物理网络 F (纯净版) ================= class Dynamical_F_Pure(nn.Module): def __init__(self, input_dim_x=17, hidden_dim=60): super(Dynamical_F_Pure, self).__init__() # 输入: x(17) + t(1) + u(1) + u_x(17) + u_t(1) = 37 (假设) # 这里动态计算维度:input_dim_x + u(1) + u_x(input_dim_x) + u_t(1) # 注意:通常 PINN 输入是 (x, t),如果 xt 混合了,维度需根据实际情况调整 # 这里假设传入 [xt, u, u_x, u_t] -> 17 + 1 + 17 + 1 = 36 total_dim = input_dim_x * 2 + 2 self.net = MLP(input_dim=total_dim, output_dim=1, layers_num=3, hidden_dim=hidden_dim) def forward(self, inputs): return self.net(inputs) # ================= 主模型 ================= class AttentionEnhancedPINN(nn.Module): def __init__(self, args): super().__init__() self.args = args self.input_dim = 17 # 假设输入维度 self.solution_u = Solution_u_Enhanced(input_dim=self.input_dim, hidden_dim=60).to(device) self.dynamical_F = Dynamical_F_Pure(input_dim_x=self.input_dim, hidden_dim=args.F_hidden_dim).to(device) # 优化器 self.optimizer = torch.optim.Adam(self.parameters(), lr=args.lr) self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(self.optimizer, T_max=args.epochs, eta_min=args.final_lr) def forward(self, xt, history_data=None): xt.requires_grad = True # 1. 预测 u u, attn_weights = self.solution_u(xt, history_data) # 2. 自动微分 # 假设 xt 的最后一位是 t,或者 t 隐含在 xt 中 # 这里假设全量求导 grads = grad(u.sum(), xt, create_graph=True, retain_graph=True)[0] u_t = grads[:, -1:] # 假设最后一列是时间导数 u_x = grads[:, :-1] # 假设前面是空间导数 # 3. 物理残差 f_input = torch.cat([xt, u, u_x, u_t], dim=1) F_val = self.dynamical_F(f_input) f = u_t - F_val return u, f, attn_weights def train_one_epoch(self, epoch, dataloader, history_loader): self.train() loss_meter = AverageMeter() if self.scheduler: self.scheduler.step() for batch in dataloader: # 解析数据:IndexedDataset 返回 (x1, x2, y1, y2, idx1, idx2) if len(batch) == 6: x1, x2, y1, y2, idx1, idx2 = batch hist1 = history_loader.get_batch(idx1) hist2 = history_loader.get_batch(idx2) else: continue x1, x2, y1, y2 = x1.to(device), x2.to(device), y1.to(device), y2.to(device) # Forward u1, f1, attn1 = self.forward(x1, hist1) u2, f2, _ = self.forward(x2, hist2) # Losses l_data = nn.L1Loss()(u1, y1) + nn.L1Loss()(u2, y2) # MAE Loss l_pde = torch.mean(f1 ** 2) + torch.mean(f2 ** 2) # MSE Loss l_phy = torch.mean(((u2 - u1) - (y2 - y1)) ** 2) # Consistency # Regularization l_reg = 0 if attn1 is not None: l_reg = torch.mean(attn1 ** 2) # Dynamic Weights alpha = self.args.alpha if epoch > 20 else 0.0 beta = self.args.beta loss = l_data + alpha * l_pde + beta * l_phy + self.args.gamma * l_reg self.optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(self.parameters(), 1.0) self.optimizer.step() loss_meter.update(loss.item()) return loss_meter.avg def predict(self, loader, history_loader): """通用预测函数""" self.eval() true_list, pred_list = [], [] with torch.no_grad(): for batch in loader: if len(batch) >= 5: # 有索引 x = batch[0].to(device) y = batch[2].to(device) idx = batch[-1] # 假设最后一个是索引 hist = history_loader.get_batch(idx) else: x = batch[0].to(device) y = batch[2].to(device) hist = None u, _ = self.solution_u(x, hist) true_list.append(y.cpu().numpy()) pred_list.append(u.cpu().numpy()) return np.concatenate(true_list).flatten(), np.concatenate(pred_list).flatten() def Train(self, trainloader, validloader, testloader, hist_loaders): train_h, valid_h, test_h = hist_loaders best_mae = 10.0 for e in range(1, self.args.epochs + 1): train_loss = self.train_one_epoch(e, trainloader, train_h) if e % 10 == 0: # 验证 y_true_v, y_pred_v = self.predict(validloader, valid_h) mae_v, mse_v, rmse_v, r2_v = calculate_metrics(y_true_v, y_pred_v) print(f"[Epoch {e}] Loss: {train_loss:.5f} | Valid MAE: {mae_v:.5f} RMSE: {rmse_v:.5f} R2: {r2_v:.4f}") # 保存最佳并测试 if mae_v < best_mae: best_mae = mae_v if testloader: y_true_t, y_pred_t = self.predict(testloader, test_h) t_mae, t_mse, t_rmse, t_r2 = calculate_metrics(y_true_t, y_pred_t) print( f" >>> Best Model Found! Test Metrics -> MAE: {t_mae:.5f}, MSE: {t_mse:.6f}, RMSE: {t_rmse:.5f}, R2: {t_r2:.4f}") if self.args.save_folder: if not os.path.exists(self.args.save_folder): os.makedirs(self.args.save_folder) np.save(os.path.join(self.args.save_folder, 'true_label.npy'), y_true_t) np.save(os.path.join(self.args.save_folder, 'pred_label.npy'), y_pred_t) torch.save(self.state_dict(), os.path.join(self.args.save_folder, 'model.pth')) 我在pinn的基础上加入了注意机制
最新发布
12-19
import torch from torch import nn from torchsummary import summary class LeNet1D_2048(nn.Module): def __init__(self): super().__init__() # 输入形状:(batch_size, 1, 2048) # 第一卷积层 self.conv1 = nn.Conv1d(1, 6, kernel_size=5, padding=2) # 保持长度2048 self.act1 = nn.Sigmoid() self.pool1 = nn.AvgPool1d(kernel_size=2, stride=2) # 输出长度1024 # 第二卷积层 self.conv2 = nn.Conv1d(6, 16, kernel_size=5, padding=0) # 输出长度1024-5+1=1020 self.act2 = nn.Sigmoid() self.pool2 = nn.AvgPool1d(kernel_size=2, stride=2) # 输出长度510 # 全连接层(修正维度计算) self.flatten = nn.Flatten() self.fc1 = nn.Linear(16 * 510, 120) # 输入维度:16通道 × 510长度 self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 5) # 输出5个类别 def forward(self, x): # 特征提取 x = self.pool1(self.act1(self.conv1(x))) # 2048 → 1024 x = self.pool2(self.act2(self.conv2(x))) # 1024 → 510 # 分类器 x = self.flatten(x) x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) # 不添加softmax,因CrossEntropyLoss自带 return x # 验证网络结构 if __name__ == "__main__": device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = LeNet1D_2048().to(device) print(summary(model, (1, 2048))) # 输入形状:1通道,长度2048 import torch from torch.utils.data import Dataset, DataLoader import numpy as np class NumpyDataset(Dataset): def __init__(self, data_path, add_channel_dim=False): self.data = np.load(data_path) self.features = self.data[:, :2048] self.labels = self.data[:, -1] self.add_channel_dim = add_channel_dim # 是否添加通道维度(用于 Conv1D) def __len__(self): return len(self.data) def __getitem__(self, idx): x = torch.tensor(self.features[idx], dtype=torch.float32) label = int(self.labels[idx]) y = torch.tensor(label, dtype=torch.long) if self.add_channel_dim: x = x.unsqueeze(0) # 形状 [1, 2048] return x, y # 使用示例(适配 Conv1D) if __name__ == "__main__": dataset = NumpyDataset(data_path="D:/Desktop/LeNet1D/data/labeled_B1.npy", add_channel_dim=True) dataloader = DataLoader(dataset, batch_size=64, shuffle=True) for batch in dataloader: features, labels = batch print("特征形状(含通道):", features.shape) # 输出: torch.Size([64, 1, 2048]) print('标签实例', labels.shape) break 根据以上代码,进行后续模型训练代码和模型测试代码的编写,将数据集按百分之八十训练集和百分之二十测试集划分
05-13
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服务器上运行;
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值