导入
前几节主要讨论的是一维特征的输入(即一个x:实数)
单维:输入x是一个实数。
多维:x有不同的特征,预测对应的分类。
回归问题:输出值y 是一个实数。
分类问题:输出y是属于一个离散的集合。
数据集介绍
如下图 是个糖尿病的数据集,一行是一个样本,共有八个特征,一列是一个特征(10维)。最终输出的值是一个y(取值只有0和1,代表分类任务)
一维到多维:模型的改变
一维:x是一个实数,所以乘以一个w权重即可。
多维:因为最终的输出值y是一个实数,所以每一个Xi的值都要和一个权重w相乘。即下图的右。
转化成向量运算,可以利用并行能力来提高运行速度。
代码部分相对于上节课内容只需修改数据准备和模型部分
如何构造多层神经网络
神经网络的本质:寻找一种非线性的空间变换函数(矩阵)(从N维到一维,通过引入sigmoid等激活函数给线性变换增加非线性因子)
神经网络到底设多少层,每层多少维,一般通过超参数搜索的方法进行尝试,看什么样的设计在开发集表现比较好。
代码实现
代码运行在jupyter上
激活函数采用sigmoid函数
import numpy as np
import torch
import matplotlib.pyplot as plt
#这里之所以设置为float32是因为大部分显卡的存储都支持,只有少部分高端显卡支持double
xy = np.loadtxt('data/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.activate = torch.nn.Sigmoid()
#构建计算图,三层网络,为了简便,统一设为x,实际图应为o1,o2,o3
def forward(self, x):
x = self.activate(self.linear1(x))
x = self.activate(self.linear2(x))
x = self.activate(self.linear3(x))
return x
model = Model()
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
epoch_list = [i for i in range(1, 101)]
loss_list = []
for epoch in range(100):
# Forward
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
loss_list.append(loss.item())
print(epoch, loss.item())
# Backward
optimizer.zero_grad()
loss.backward()
# Update
optimizer.step()
plt.plot(epoch_list, loss_list)
plt.grid(True)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
注意:diabetes.csv数据集如果加载不出:原因是该数据集和源代码没有放置在同一个文件夹内(必须要放在同一个文件夹内)
结果展示
激活函数用ReLU函数实现
import numpy as np
import torch
import matplotlib.pyplot as plt
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.activate = torch.nn.ReLU()
self.sigmoid = torch.nn.Sigmoid()
#最后一层使用sigmoid,保证概率输出曲线光滑,且relu输出如果小于1,他是直接输出0的, 所以sigmoid就可以得到小数,o-
#1之间的取值)
def forward(self, x):
x = self.activate(self.linear1(x))
x = self.activate(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
epoch_list = [i for i in range(1, 101)]
loss_list = []
for epoch in range(100):
# Forward
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
loss_list.append(loss.item())
print(epoch, loss.item())
# Backward
optimizer.zero_grad()
loss.backward()
# Update
optimizer.step()
plt.plot(epoch_list, loss_list)
plt.grid(True)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
结果展示
注意:即使是相同的超参数设置,每次训练的曲线也是不同的