一维与多维输入代码有什么区别?
1.输入端不同:
之前logistics的代码输入x是一维的,包含三个样本。选择直接设置(x,y)
现在的输入x是十维的,包含442个样本,需要导入数据集文件。
使用x=np.loadtxt()函数导入文件。
numpy.loadtxt(fname, dtype=, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0)
下列代码中用到的参数是fname:文件名,delimiter分隔符和dtype数据类型。
老师视频里面的:xy=np.loadtxt('diabetes.csv,gz',delimiter=',',dtype=np.float32)
应该是将diabetes_data.csv.gz和diabetes_target.csv.gz的数据合并了,
前面8列都是x,最后一列是y。
如果没有调整过数据集,只用anaconda自带的数据集。在导入数据集的时候要分别导入x,y。
然后把数组转化为张量。
把数组转化为张量可以使用torch.Tensor(x)和torch.from_numpy(x)
#用老师提供的数据库xy=np.loadtxt('diabetes.csv,gz',delimiter=',',dtype=np.float32)
#用自带的
#x=np.loadtxt('diabetes_data.csv.gz',delimiter=',',dtype=np.float32)
#y=np.loadtxt('diabetes_target.csv.gz',delimiter=',',dtype=np.float32)
#直接输入文件名报错
x=np.loadtxt("D:\\anaconda3\\Lib\\site-packages\\sklearn\\datasets\\data\\diabetes_data.csv\\X.txt",delimiter=' ',dtype=np.float32)
y=np.loadtxt("D:\\anaconda3\\Lib\\site-packages\\sklearn\\datasets\\data\\diabetes_data.csv\\y.txt",delimiter=' ',dtype=np.float32)
x_data=torch.from_numpy(x)
y_data=torch.from_numpy(y)#把数组转化成张量
2.设计类:
#设计类
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
#为什么不直接一次性降多维?
#会丢失特征:例如在图像处理中会丢失像素点。
self.linear1 = torch.nn.Linear(10,6)
self.linear2 = torch.nn.Linear(6,4)
self.linear3 = torch.nn.Linear(4,1)
self.sigmoid = torch.nn.Sigmoid()
#计算预测值y
def forward(self,x):
#self 参数是对类的当前实例的引用,用于访问属于该类的变量。
x=self.sigmoid(self.linear1(x))
x=self.sigmoid(self.linear2(x))
x=self.sigmoid(self.linear3(x))
return x
由于一维输入时,输出只有一维,因此只要写一遍就可以求出预测值。
y_pred = torch.sigmoid(self.linear(x))
而多维输入时,输出只有一维,就要把多维的数据进行降维操作。
anaconda自带的数据集中x是十维的,若直接降维,
则:self.linear1 = torch.nn.Linear(10,1) 1便是输出的维度。
但是直接降维可能会丢失特征:例如在图像处理中会丢失像素点。所以使用多次降维的方法。
多次降维操作图解:
def forward(self,x):
#self 参数是对类的当前实例的引用,用于访问属于该类的变量。
o1=self.sigmoid(self.linear1(x))
o2=self.sigmoid(self.linear2(o1))
y_pred=self.sigmoid(self.linear3(o2))
return y_pred
由于每一层的输出又变成下一层的输入,所以我们可以不用定义新的变量,直接使用x即可。
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
#为什么不直接一次性降多维?
#会丢失特征:例如在图像处理中会丢失像素点。
self.linear1 = torch.nn.Linear(10,6)
self.linear2 = torch.nn.Linear(6,4)
self.linear3 = torch.nn.Linear(4,1)
self.sigmoid = torch.nn.Sigmoid()
#计算预测值y
def forward(self,x):
#self 参数是对类的当前实例的引用,用于访问属于该类的变量。
x=self.sigmoid(self.linear1(x))
x=self.sigmoid(self.linear2(x))
x=self.sigmoid(self.linear3(x))
return x
调用测试集的方法不同。
但是降维几次比较合适这个问题我还不会。
用自带的数据集跑出来的数据太奇怪了,损失有350多,我改用老师的数据集。
多维特征输入的老师代码 :
我写的代码:使用老师提供的数据集。
import torch
import numpy as np
import matplotlib.pyplot as plt
epoch1=[]
item=[]
xy=np.loadtxt('D:\\project\\.vscode\\.vscode\\diabetes.csv.gz',delimiter=',',dtype=np.float32)#加载训练集合
x_data = torch.from_numpy(xy[:,:-1])#取前八列
y_data = torch.from_numpy(xy[:,[-1]])#取最后一列
class Model(torch.nn.Module):
def __init__(self):#构造函数
super(Model,self).__init__()
self.linear1 = torch.nn.Linear(8,6)#8维到6维
self.linear2 = torch.nn.Linear(6, 4)#6维到4维
self.linear3 = torch.nn.Linear(4, 1)#4维到1维
self.sigmoid = torch.nn.Sigmoid()
#y_pred就是预测值
def forward(self, x):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()#实例化
criterion = torch.nn.BCELoss(reduction='mean')
#老师使用的是torch.nn.BCELoss(size_average=False)但是我使用这个损失太大了
optimizer = torch.optim.SGD(model.parameters(),lr=0.1)#lr为学习率,因为0.01太小了,我改成了0.1
for epoch in range(1000):
#Forward
y_pred = model(x_data)
loss = criterion(y_pred,y_data)
print(epoch,loss.item())
#Backward
optimizer.zero_grad()
loss.backward()
#update
optimizer.step()
epoch1.append(epoch)
item.append(loss.item())
plt.plot(epoch1,item)
plt.ylabel('item')
plt.xlabel('epoch')
plt.show()
学习率时0.01时:
学习率时0.1时:
学习率时1时:
使用anaconda自带的数据集:
因为自带的数据集中的y没有集中在【0,1】之间,所以使用激活函数
y_data = torch.sigmoid(y_data)把y映射到【0,1】之间。
import torch
import numpy as np
import matplotlib.pyplot as plt
epoch1=[]
item=[]
x=np.loadtxt("D:\\project\\.vscode\\.vscode\\diabetes_data.csv.gz",delimiter=' ',dtype=np.float32)#加载训练集合
y=np.loadtxt("D:\\project\\.vscode\\.vscode\\diabetes_target.csv.gz",delimiter=',',dtype=np.float32)#加载训练集合
x_data = torch.from_numpy(x)
y_data = torch.from_numpy(y)
y_data =torch.sigmoid(y_data)
print("1",x_data.shape[0])
print("1",y_data.shape[0])
class Model(torch.nn.Module):
def __init__(self):#构造函数
super(Model,self).__init__()
self.linear1 = torch.nn.Linear(10,8)#8维到6维
self.linear2 = torch.nn.Linear(8, 4)#6维到4维
self.linear3 = torch.nn.Linear(4, 1)#4维到1维
self.sigmoid = torch.nn.Sigmoid()
#y_pred就是预测值
def forward(self, x):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()#实例化
criterion = torch.nn.BCELoss(size_average=True)
#老师使用的是torch.nn.BCELoss(size_average=False)但是我使用这个损失太大了
optimizer = torch.optim.SGD(model.parameters(),lr=0.1)#lr为学习率,因为0.01太小了,我改成了0.1
for epoch in range(1000):
#Forward
y_pred = model(x_data)
y = y_pred.squeeze()
loss = criterion(y,y_data)
print(epoch,loss.item())
#Backward
optimizer.zero_grad()
loss.backward()
#update
optimizer.step()
epoch1.append(epoch)
item.append(loss.item())
plt.plot(epoch1,item)
plt.ylabel('item')
plt.xlabel('epoch')
plt.show()
加载数据集
使用的损失函数,优化器,训练集和多维度输入都是一致的。
只需要补充一部分代码:
1.定义类Diabetes
Dataset:是抽象类:不能实例化,只能继承。
需要设置类继承Dataset的方法和属性:
class Diabetes(Dataset):
def __init__(self,filepath):
xy=np.loadtxt(filepath,delimiter=',',dtype=np.float32)
self.len=xy.shape[0]
self.x_data=torch.from_numpy(xy[:,:-1])
self.y_data=torch.from_numpy(xy[:,[-1]])
def __getitem__(self, index) :#魔法函数,返回对应的x和y,给train_loader使用
return self.x_data[index],self.y_data[index]
def __len__(self):
return self.len
xy=np.loadtxt(filepath,delimiter=',',dtype=np.float32)就是导入数据集,filepath就是文件路径。
dataset=Diabetes("D:\\project\\.vscode\\.vscode\\diabetes.csv.gz")
只是放到类的后面再输入参数而已。
类中补充的两个函数:
getiem()支持索引,拿数据
_len_ len() 可以返回数据集的长度
为什么需要这两个函数?
因为我们需要使用DataLoader,DataLoader需要索引和长度的值,DataLoader的作用是打乱样本集的顺序。
为什么需要打乱样本集的顺序?
为了加强模型的泛化能力,有时候需要打乱数据集(包括特征数据和标签),但是要保证每一条数据中的特征数据和标签的对应关系。
2.使用DataLoader
train_loader=DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=0)
DataLoader的参数:
系统学习Pytorch笔记三:Pytorch数据读取机制(DataLoader)与图像预处理模块(transforms)_翻滚的小@强的博客-CSDN博客_dataloader pytorch
在处理数据的时候,使用了minibatch的方法:
把数据集的样本打乱顺序后,分装成若干个小的数据集。
分析图解:
数据集数据:sample1-8
shuffle=True 打乱数据
loader分装成若干个小的数据集,每个小数据集叫做Batch。
3.训练过程:
if __name__ == '__main__':
windows系统必须使用,否则会报错。
for i,data in enumerate(train_loader,0):
#输入输出
x_data,y_data=data
enumerate(train_loader,0)
enumerate(序列,索引)
表示从0开始返回序列里面的元素。
if __name__ == '__main__':
for epoch in range(100):
sum=0
for i,data in enumerate(train_loader,0):
#输入输出
x_data,y_data=data
y_pred=model(x_data)
loss = criterion(y_pred,y_data)
print(epoch,i,loss.item())
optimisim.zero_grad()
loss.backward()
optimisim.step()
代码复现:使用的时老师发布的数据集。
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import torch
import numpy as np
import matplotlib.pyplot as plt
class Diabetes(Dataset):
def __init__(self,filepath):
xy=np.loadtxt(filepath,delimiter=',',dtype=np.float32)
self.len=xy.shape[0]
self.x_data=torch.from_numpy(xy[:,:-1])
self.y_data=torch.from_numpy(xy[:,[-1]])
def __getitem__(self, index) :#魔法函数,返回对应的x和y,给train_loader使用
return self.x_data[index],self.y_data[index]
def __len__(self):
return self.len
dataset=Diabetes("D:\\project\\.vscode\\.vscode\\diabetes.csv.gz")
train_loader=DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=0)
print(train_loader)
class Model(torch.nn.Module):
def __init__(self) :
super(Model,self).__init__()
self.linear1=torch.nn.Linear(8,6)
self.linear2=torch.nn.Linear(6,4)
self.linear3=torch.nn.Linear(4,1)
self.sigmoid=torch.nn.Sigmoid()
def forward(self,x):
x=self.sigmoid(self.linear1(x))
x=self.sigmoid(self.linear2(x))
x=self.sigmoid(self.linear3(x))
return x #避免出现参数传递错误,就不设置新参数而是选择x自动代换
model=Model()
criterion=torch.nn.BCELoss(size_average=True)
optimisim=torch.optim.SGD(model.parameters(),lr=0.1)
e_ch=[]
loss_l=[]
if __name__ == '__main__':
for epoch in range(100):
sum=0
for i,data in enumerate(train_loader,0):
#输入输出
x_data,y_data=data
y_pred=model(x_data)
loss = criterion(y_pred,y_data)
print(epoch,i,loss.item())
optimisim.zero_grad()
loss.backward()
optimisim.step()
e_ch.append(epoch)
sum+=loss.item()
print("1",sum)
loss_l.append(sum/23)
plt.plot(e_ch,loss_l)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()
图像非常的离谱。震荡很明显,还没有找到解决措施。
模型训练时loss震荡严重的几个解决方案_wx62cea850b9e28的技术博客_51CTO博客
根据这个博客进行了调参:
还是非常奇怪,loss震荡,没有找到解决措施。
代码复现:
使用anaconda自带的数据集:
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import torch
import numpy as np
import matplotlib.pyplot as plt
class Diabetes(Dataset):
def __init__(self,filepath1,filepath2):
x=np.loadtxt(filepath1,delimiter=' ',dtype=np.float32)
y=np.loadtxt(filepath2,delimiter=',',dtype=np.float32)
self.len=x.shape[0]
self.x_data=torch.from_numpy(x)
self.y_data=torch.from_numpy(y)
def __getitem__(self, index) :#魔法函数,返回对应的x和y,给train_loader使用
return self.x_data[index],self.y_data[index]
def __len__(self):
return self.len
dataset=Diabetes('D:\\project\\.vscode\\.vscode\\diabetes_data.csv.gz','D:\\project\\.vscode\\.vscode\\diabetes_target.csv.gz')
train_loader=DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=0)
print(train_loader)
class Model(torch.nn.Module):
def __init__(self) :
super(Model,self).__init__()
self.linear1=torch.nn.Linear(10,6)
self.linear2=torch.nn.Linear(6,4)
self.linear3=torch.nn.Linear(4,1)
self.sigmoid=torch.nn.Sigmoid()
def forward(self,x):
x=self.sigmoid(self.linear1(x))
x=self.sigmoid(self.linear2(x))
x=self.sigmoid(self.linear3(x))
return x #避免出现参数传递错误,就不设置新参数而是选择x自动代换
model=Model()
criterion=torch.nn.BCELoss(size_average=True)
optimisim=torch.optim.SGD(model.parameters(),lr=0.3)
e_ch=[]
loss_l=[]
if __name__ == '__main__':
for epoch in range(100):
sum=0
for i,data in enumerate(train_loader,0):
#输入输出
x_data,y_data=data
y_pred=model(x_data)
y = y_pred.squeeze()
y_data = torch.sigmoid(y_data)
loss = criterion(y,y_data)
print(epoch,i,loss.item())
optimisim.zero_grad()
loss.backward()
optimisim.step()
e_ch.append(epoch)
sum+=loss.item()
print("1",sum)
loss_l.append(sum/23)
plt.plot(e_ch,loss_l)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()
图像: