目录
初学深度学习
知识理解:
欠拟合和过拟合:过拟合是指模型在训练数据上表现的太好,但在训练时学习了不必要的噪声和细节,导致测试数据误差很高。欠拟合是指模型过于简单,导致模型在训练数据以及测试数据上都表现的很差。
过拟合的解决办法,数据增强,早停,正则化,减少模型复杂度,获取更多数据,交叉验证,dropout。
欠拟合的解决办法,增加模型复杂度,减少正则化,增加训练时间,使用更强大的模型。(这里的潜在模式是指数据背后的规律,趋势和特征)
要求:通过一个人的外貌、性格、财富和内涵这四个维度的得分,计算他的恋爱次数
1、导入相关库
import torch # 导入深度学习库 用于计算张量和自动微分(计算梯度)
import matplotlib.pyplot as plt # 画图的 导入画图库
import random # 随机 导入打乱数据的库
2、生成训练用的数据
def create_data(w, b, date_num): #定义生成数据的函数 传入参数w(权重),b(偏移值),要生成的样本数量
x_ = torch.normal(0, 1, (date_num, len(w))) #根据传入的参数w和b生成X 0均值 1为标准差 形状为data_num * len(w)的矩阵
y_ = torch.matmul(x_, w) + b # matmul表示矩阵相乘 根据w,b,x计算Y
noise = torch.normal(0, 0.01, y_.shape) # 噪声要加到y上 由于传入的参数会与现实有差距,定义噪声 均值0 标准差0.01 形状和Y相同
y_ += noise # 加上噪声得到最终的Y
return x_, y_ # 返回生成的数据X,Y
num = 500 # 要生成的样本数量
true_w = torch.tensor([8.1, 2, 2, 4]) #定义真实的w和b用以对比
true_b = torch.tensor(1.1)
x, y = create_data(true_w, true_b, num) #通过生成数据的函数,生成X和Y
# plt.scatter(x[ :, 3], y, 1) #画出散点图查看 参数 为x矩阵的某一列 Y 保证用来绘制的X和Y数量一样大 点的大小为1 可视化 画图
# plt.show()
3、训练模型时提供数据
def data_provide(data, lable, batchsize): #定义一个能提供一批数据的函数 传入参数x,y以及步长
length = len(lable) #得到Y的维度
indices = list(range(length)) #打乱索引列表 函数将传入的X和Y(已知的x和y)打乱传回,保证随机性
random.shuffle(indices)
for each in range(0, length, batchsize): #使用有存档点的return,先返回一批数据
get_indices = indices[each: each + batchsize]
get_data = data[get_indices]
get_label = lable[get_indices]
yield get_data, get_label
batchsize = 16 #定义步长
4、定义模型
def fun(x, w, b): #定义一个模型(函数) 传入参数x,w,b 计算预测的y
pre_y = torch.matmul(x, w) + b #计算预测值y
return pre_y #返回预测值y
5、定义loss函数和梯度下降函数(优化器)
def maeloss(pre_y, y): #定义损失函数 传入真实值y和预测值y
return torch.sum(abs(pre_y - y)) / len(y) #返回计算出的loss
def sgd(paras, lr): #定义梯度下降函数,更新参数w,b 传入参数以及学习率
with torch.no_grad(): #梯度下降过程中不计算新的梯度
for para in paras: #更新传入的参数 注意!!!! python语法 para -= para.grad * lr 不能写成 para = para - para.grad*lr
para -= para.grad * lr
para.grad.zero_() #使用过的梯度要归0 使用同一个参数的梯度会叠加,导致其他参数的更新不正确
相关参数
lr = 0.03 #定义学习率以及初始参数w和b
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad = True)#定义w 传入参数 均值 标准差 形状 声明是否要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True) #定义b 传入参数为一个值,声明是否要计算梯度
print(w_0, b_0) #打印出初始w和b看一下
6、进行训练
#!!!开始训练模型
epochs = 50 #定义训练轮数
for epoch in range(epochs): #每一轮训练
data_loss = 0 #定义变量统计每一轮的loos值
for batch_x, batch_y in data_provide(x, y, batchsize): #每轮训练数据分多批
pre_y = fun(batch_x, w_0, b_0) #获取每一批的预测y值和loss值
loss = maeloss(pre_y, batch_y)
loss.backward() #得到loss后梯度回传
sgd([w_0, b_0], lr) #梯度下降 更新未知参数
data_loss += loss #统计这一批loos值
print("epoch %03d: loss: %.6f"%(epoch, data_loss)) #打印出每轮的loos值查看
#查看真实未知参数值与预测的未知参数值
print("真实的函数值是", true_w, true_b)
print("训练得到的参数值是", w_0, b_0)
7、可视化,看一下训练效果
#进行一次可视化,画图
idx = 3
plt.plot(x[:, idx].detach().numpy(), x[:, idx].detach().numpy() * w_0[idx].detach().numpy() + b_0.detach().numpy())
plt.scatter(x[:, idx], y, 1)
plt.show()