多维度输入问题和加载数据集

一维与多维输入代码有什么区别?

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)

torch.from_numpy VS torch.Tensor_麦克斯韦恶魔的博客-CSDN博客https://blog.csdn.net/github_28260175/article/details/105382060

#用老师提供的数据库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多,我改用老师的数据集。

多维特征输入的老师代码 :

PyTorch学习(六)--处理多维特征的输入_陈同学爱吃方便面的博客-CSDN博客https://blog.csdn.net/weixin_44841652/article/details/105125826

我写的代码:使用老师提供的数据集。

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开始返回序列里面的元素。

for batch_idx(或者i), data in enumerate(train_loader, 0): 到底是什么意思_波尔德的博客-CSDN博客_enumerate(train_loader,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()

图像:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值