1.线性模型输入输出
线性模型的输入是多维特征的样本,每个样本对应一个输出。可以抽象地理解为一个同学是一个样本,每个同学测试“身高、体重、视力、色盲”等身体状况,根据这些特征判断该同学是否健康,健康为1,不健康为0。
2.torch.nn.Linear线性模块
基础线性模型的网络架构如图所示,训练目的就是优化权重参数(w和b)使得损失loss最小,损失函数的计算公式可以根据需要选择。
如果是二分类问题,那么输出应该是属于某一类的概率,需要使用非线性函数(sigmoid函数)将y映射到[0,1]之间,且非线性函数可以提高模型的非线性学习能力,能够更好地拟合模型。
模型进一步演变为下图所示,使用BCE Loss(Binary Cross-Entropy Loss二元交叉熵损失)计算模型预测的概率分布与真实标签的概率分布之间的差异。损失值越小,表示模型的预测越准确。
import torch
import numpy as np
import matplotlib.pyplot as plt
# import torch.nn.functional as F
x_data=torch.Tensor([[1],[2],[3]])
y_data=torch.Tensor([[0],[1],[1]])#二分类问题
class LogisticRegressionModel(torch.nn.Module):
def __init__(self):
super(LogisticRegressionModel,self).__init__() #延续父类的功能并进一步扩展
self.linear=torch.nn.Linear(1,1) #构造一个线性模块
def forward(self,x):
y_pred=torch.sigmoid(self.linear(x)) #📢映射函数,将线性模型输出映射到[0,1]区间
return y_pred
model=LogisticRegressionModel()
criterion=torch.nn.BCELoss(size_average=False) #计算损失,括号内的参数是是否算平均值
optimizer=torch.optim.SGD(model.parameters(),lr=0.01) #自动寻找模型中所有需要优化的权重系数 学习率
n=100
loss_list=[]
for epoch in range(n):
y_pred=model(x_data) #forward函数写在callable函数块内了,所以可以直接把模块名当函数名
loss=criterion(y_pred,y_data)
loss_list.append(loss.item()) #loss同样是一个张量,只取数值就用item
optimizer.zero_grad() #权重梯度手动清零
loss.backward() #反馈自动计算下降梯度
optimizer.step() #自动更新权重值
print('w=',model.linear.weight.item())
print('b=',model.linear.bias.item())
x=np.linspace(0,10,200)
x_t=torch.Tensor(x).view((200,1)) #reshape
y_t=model(x_t)
y=y_t.data.numpy() #把y数据变成一个矩阵
plt.plot(x,y)
plt.plot([0,10],[0.5,0.5],c='r')
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()
plt.show()
3.多层线性模型
把一层线性模型看出一个特征提取器,则多层线性模型就可以提取多层信息,且提高整个模型的非线性学习能力。而且,如果直接从高维映射到低维,可能会遇到梯度消失或梯度爆炸的问题。
import numpy as np
import torch
xy=np.loadtxt('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)
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
model=Model()
criterion=torch.nn.BCELoss(size_average=True) #计算损失,括号内的参数是是否算平均值
optimizer=torch.optim.SGD(model.parameters(),lr=0.01)
loss_list=[]
for epoch in range(100):
y_pred=model(x_data)
loss=criterion(y_pred,y_data)
loss_list.append(loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
plt.plot(range(100),loss_list)
plt.grid()
plt.show()
运行结果如图所示
4.jupyter notebook导入数据集
jupyter notebook需要将数据集先下载,然后再导入(复制粘贴)到所在文件夹
再使用以下代码调用数据集
np.loadtxt('diabetes.csv.gz',delimiter=',',dtype=np.float32)
-
fname
:文件名或文件路径,指定要从中加载数据的文件。 -
dtype
:数据类型,默认为float
。指定数组中元素的数据类型。 -
comments
:注释字符,默认为'#'
。指定文件中注释的起始字符,加载时会忽略以该字符开始的行。 -
delimiter
:分隔符,默认为None
。指定字段之间的分隔符,如果为None
,则任何空白字符(如空格、制表符等)都被视为分隔符。 -
converters
:转换器,默认为None
。一个字典或函数,用于将数据转换为指定的数据类型。 -
skiprows
:跳过的行数,默认为0
。指定在开始解析前要跳过的行数。 -
usecols
:使用的列,默认为None
。指定要加载的列,可以是列的索引列表或切片对象。 -
unpack
:是否解包,默认为False
。如果为True
,则返回一个元组,其中每个元素是一列的数据。 -
ndmin
:最小维度,默认为0
。指定返回数组的最小维度。 -
encoding
:编码,默认为None
。指定文件的编码方式。 -
max_rows
:最大行数,默认为None
。指定要加载的最大行数。 -
quotechar
:引用字符,默认为None
。指定用于引用字段的字符,通常用于包含分隔符的字段。 -
like
:参考对象,默认为None
。指定一个数组,用于确定数据类型和其他参数。