从实现角度整理神经网络框架及其他要点

torch网络框架

读取文件

数据预处理

构造数据加载类

# 1. Dataset
# 定义获取数据集的类。继承基类Dataset,自定义数据集及对应标签
class mydataset(Dataset):
	# 读取加载数据 
    def __init__(self,data_x,data_y_source): # data_x是训练数据,data_y_source是标签,数据类型是nd.array(创建的时候是list,转成的array),数据要对齐,
        self._x=data_x
        self._y=data_y_source
        self._len=data_y_source.shape[0]
    def __getitem__(self,item):
        return self._x[item],self._y[item]
    def __len__(self):# 返回整个数据的长度
        return self._len
# 获取数据,集中数据
data_dataset=mydataset(data_x,data_y_source)
print(data_dataset[2]) # 相当于调用__getitem__(2)
print(data_dataset.__len__())
# 以上数据以tuple返回,每次只返回一个样本,实际上,Dataset只负责数据的抽取
# 如果希望批量处理batch,同时进行shuffle和并行加速等操作,可选择DataLoader。
# 可以实例化一个dataset,然后用Dataloader 包起来
data_set_loader = DataLoader(data_dataset, batch_size=4,shuffle=True)

# 2. DataLoader
# DataLoader的格式:[https://blog.csdn.net/wuyanne/article/details/120768148](https://blog.csdn.net/wuyanne/article/details/120768148)
# 实现
data_loader = data.DataLoader(data,batch_size=2,shuffle=False,num_workers=2)
# 读取
for i, traindata in enumerate(test_loader):
	print('i:', i)
	Data,Label = traindata
	print('Data:',Data)
	print('Label:',Label)
# 迭代
# 可以像使用迭代器一样使用它,比如进行循环操作,可以通过iter命令将其转换为迭代器
dataiter = iter(data_loader)

划分数据集

# 1 数据加载类划分
# 划分 训练集 测试集, 随机混乱顺序划分的     四舍五入
train_data,test_data=random_split(data_dataset,[round(0.8*data_dataset._len),round(0.2*data_dataset._len)])#这个参数有的版本没有 generator=torch.Generator().manual_seed(0)

# 2 
train_test_split


搭建模型

__init__函数和forward函数必须要有,class函数自动执行这两个函数,__init__函数中要定义整个网络中的所有网络层,前馈函数里要根据整个网络把__init__函数中定义的网络层连起来。

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class Net(nn.Module):
	def __init__(self):
		...
	def forward(self,x):
		...
	def ...

搭建网络

定义所有要用到的网络层
比喻:制作积木块

  • 要注意维度问题,目前我是根据报错调试程序,程序说它需要什么类型的数据我就给他什么类型的数据
	def __init__(self):
        #使用super()方法调用基类的构造器,即nn.Module.__init__(self)
        super(CNN,self).__init__()
        # 1 input image channel ,6 output channels,5x5 square convolution kernel
        self.conv1=nn.Conv1d(500,12,2)
        # 6 input channl,16 output channels,5x5 square convolution kernel
        self.conv2=nn.Conv1d(6,16,4)
        # an affine operation:y=Wx+b
        self.fc1=nn.Linear(32,16)
        self.fc2=nn.Linear(16,8)
        self.fc3=nn.Linear(8,1)
        self.pool = nn.MaxPool2d(2, 2)
        self.Sigmoid = nn.Sigmoid ()

前馈函数

将__init__函数中定义的各个网络层输入输出衔接起来
比喻:把积木块搭起来,用线串起来

  • 网络的输入x,通常数据类型为张量,如果要用cuda并行,记得把x放入gpu
  • 全连接层可以和激活函数写在一起,代码简洁并且不会忘写激活函数
	def forward(self,x):
        # x是网络的输入,然后将x前向传播,最后得到输出
        x=torch.Tensor(x).to(device)
        x=x.unsqueeze(0) # 输入,根据需要判断是否需要多加维度,比如LSTM、CNN需要三维数据,二维数据进来要多加一个维度
        x=self.Sigmoid(self.conv1(x)) # 一个一维卷积层,一个sigmoid层
        x=self.pool(x) # 定义了2x2的池化层
        x=self.Sigmoid(self.conv2(x))
        x=x.view(-1,self.num_flat_features(x)) 将x拉伸成一维张量,进行
        x=self.Sigmoid(self.fc1(x))
        x=self.Sigmoid(self.fc2(x))
        x=self.fc3(x)
        return x[0]
        
    # 根据需要,自己定义的方法。
    # 计算张量中共有多少个有效数据,计算数量,便于拉伸成一维张量
	def num_flat_features(self,x): 
        size=x.size()[1:] # 例如x的形状是[1, 16, 2],取出的size形状是[16, 2]
        num_features=1
        for s in size:# s的值分别为16,2,依次相乘,则为数据总数量
            num_features*=s
        return num_features # 返回的类型是int,一个数字

查看模型参数

for i in model.parameters():
    print(i.shape)

创建模型类的对象,定义损失函数和优化器

model = Net().to(device)
loss_function = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)#建立优化器实例
print(model)

测试模型性能

这个函数是测试用来测试x_test y_test 数据

def eval(model): # 返回的是这10个 测试数据的平均loss
    test_epoch_loss=[]
    with torch.no_grad():
        optimizer.zero_grad()
        for i in range(0,10):
            y_pre = model(x_test[i])
            y_tru=torch.Tensor([y_test[i]]).to(device)
            test_loss = loss_function(y_pre,y_tru)
            test_epoch_loss.append(test_loss.item())
    return mean(test_epoch_loss)

定义数组分别存放训练和测试的损失,对整个训练过程重复epochs次迭代,每一次迭代中,需要逐个将训练集中的个体放入模型进行训练,

epochs =100
sum_train_epoch_loss=[] # 存储每个epoch 下 训练train数据的loss
sum_test_epoch_loss=[]  # 存储每个epoch 下 测试 test数据的loss
for epoch in range(epochs):
    epoch_loss=[]
    for i in range(0,85):
        #清除网络先前的梯度值
        optimizer.zero_grad()
        y_pred = model(x_train[i])
        y_true=torch.Tensor([y_train[i]]).to(device)
        #训练过程中,正向传播生成网络的输出,计算输出和实际值之间的损失值
        print("y_pred:",y_pred,",y_true:",y_true)
        single_loss = loss_function(y_pred,y_true)
        epoch_loss.append(single_loss.item())
        single_loss.backward()#调用backward()自动生成梯度
        optimizer.step()#使用optimizer.step()执行优化器,把梯度传播回每个网络 

    train_epoch_loss=mean(epoch_loss)   
    test_epoch_loss=eval(model)#返回的是这10个 测试数据的平均loss
    sum_train_epoch_loss.append(train_epoch_loss)
    sum_test_epoch_loss.append(test_epoch_loss)
    print("epoch:"+str(epoch)+"  train_epoch_loss: "+str(train_epoch_loss)+"  test_epoch_loss: "+str(test_epoch_loss))

tensorflow


model.fit()

dataloader使用

# 构造数据加载类 
class mydataset(Dataset):
    def __init__(self,data_x,data_y_source): # 读取加载数据 torch.tensor
        self._x=data_x
        self._y=data_y_source
        self._len=data_y_source.shape[0]
    def __getitem__(self,item):
        return self._x[item],self._y[item]
    def __len__(self):# 返回整个数据的长度
        return self._len

# 划分 训练集 测试集
data_dataset=mydataset(data_x,data_y_source) # data_x是训练数据,data_y_source是标签,数据要对齐
train_data,test_data=random_split(data_dataset,[round(0.8*data_dataset._len),round(0.2*data_dataset._len)])#这个参数有的版本没有 generator=torch.Generator().manual_seed(0)
#                     随机混乱顺序划分的     四舍五入

# 将训练和测试数据集放入dataloader中,可以设置batch进行训练
epochs =100
batch_size=10
test_loader = DataLoader(test_data, batch_size = batch_size, shuffle = True, num_workers = 0 , drop_last=False)
train_loader = DataLoader(train_data, batch_size = batch_size, shuffle = True, num_workers = 0 , drop_last=False)

在这里插入图片描述

调试tip总结

池化层定义

torch:两种定义方法

# 1
	# __init__()
	self.pool = nn.MaxPool2d(2, 2) # 平均池化层是nn.AvgPool2d
	# forward()
	x = self.pool(x)
# 2
	import torch.nn.functional as F
	# forward()
	x = F.max_pool2d(x, 2) # 平均池化层是F.avg_pool2d
	

激活函数

# sigmoid
	# __init__()
	self.sigmoid = torch.nn.Sigmoid()
	# forward()
	x = self.sigmoid(x)

# softmax
	# __init__()
	self.softmax = torch.nn.Softmax(dim = 1) # 或 dim = 0
	# forward()
	x = self.softmax(x)
	
# relu
	# __init__()
	self.relu= torch.nn.ReLU()
	# forward()
	x = self.relu(x)

# tanh
	# __init__()
	self.tanh= torch.nn.Tanh()
	# forward()
	x = self.tanh(x)

优化器

# 集合,使用多种优化器预测
# 不同优化器不同的定义方法
net_SGD = Net()
net_Momentum = Net()
net_RMSProp = Net()
net_Adam = Net()

nets = [net_SGD, net_Momentum, net_RMSProp, net_Adam]

opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)
opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.9)
opt_RMSProp = torch.optim.RMSprop(net_RMSProp.parameters(), lr=LR, alpha=0.9)
opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99))

optimizers = [opt_SGD, opt_Momentum, opt_RMSProp, opt_Adam]

LSTM

		# forward()
		x=torch.Tensor(x).to(device)
		# x.shape = [500, 12]
        x=x.unsqueeze(1) # LSTM的输入是三维的,二维数据进来要多加一个维度
        # x.shape = [500, 1, 12]
        lstm_out,(h_n,h_c) = self.lstm_1(x,None)
        # lstm_out.shape = [500, 1, 128], type(lstm_out) = <class 'torch.Tensor'>
        prediction=lstm_out[-1]
        # prediction.shape = [1, 128], type(prediction) = <class 'torch.Tensor'>
        # prediction就是一维张量,可以直接放入全连接层
        prediction = self.linear_1(prediction)

CNN

没有batch的情况

		# forward()
		x=torch.Tensor(x).to(device)
		# x.shape = [500, 12]
        x=x.unsqueeze(0) #CNN的输入是三维的,二维数据进来要多加一个维度
        # x.shape = [1, 500, 12]
        x=self.conv1(x)
		# x.shape = [1, 12, 11]
        x=self.Sigmoid(x)
		# x.shape = [1, 12, 11]
        x=F.max_pool2d(x,(2,2))
        # x.shape = [1, 6, 5]
        x=self.conv2(x)
		# x.shape = [1, 16, 2]
		x=self.Sigmoid(x)
        # x.shape = [1, 16, 2]
        x=x.view(-1,self.num_flat_features(x))
        # x.shape = 
        x=self.fc1(x)
        ...

使用了数据加载器,设置了batch_size的情况,x需要转换一下维度

		# forward()
		# x.shape = [10, 600, 12]
		x.transpose(0,1) # x需要转换一下维度
        x=torch.Tensor(x).to(device)
        # x.shape = [1, 500, 12]
        x=self.Sigmoid(self.conv1(x))
		# x.shape = [1, 12, 11]
        x=x.view(-1,self.num_flat_features(x))
        # x.shape = [10, 132]
        x=self.Sigmoid(self.fc1(x))
		# x.shape = [10, 66]
		x=self.Sigmoid(self.fc2(x))
		# x.shape = [10, 33]
		x=self.fc3(x)
		# x.shape = [10, 1]
        ...

写csv

为csv添加表头

import pandas as pd
df = pd.read_csv('tf.csv',header=None,names=['a','b','c','d','e','f','g','h','i','j','k'])
df.to_csv('tf.csv',index=False) # 先存再写
plt.plot(list(nums_zd.keys()),list(nums_zd.values()),'o-',color = 'r',label="CNN-RLSTM")
plt.legend() # 有这句话,上面定义的label="CNN-RLSTM"才会显示出来

模型保存

model = Net()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值