深度学习复习笔记(5)简单线性回归

# 整体思路:
# 1、创建数据
# 2、创建模型(函数),Loss,梯度下降
# 3、随机选取初始参数,根据loss和梯度下降更新参数
# 4、可视化

import torch                        #深度学习框架
import matplotlib.pyplot as plt     #画图的

import random                       #随机操作

#生成数据函数
def create_data(w, b, data_num):
    x = torch.normal(0, 1, (data_num, len(w)))      #(平均,标准差,规格)data_num为长,w的个数为宽
    y = torch.matmul(x, w) + b                      #matmul矩阵相乘,一定要tensor相乘,即x,w为tensor

    noise = torch.normal(0, 0.01, y.shape)          #添加噪声
    y += noise                                      #噪声加到y上

    return x, y

#假设知道w, b真实值
num = 500
true_w = torch.tensor([8.1, 2, 2, 4])
true_b = torch.tensor(1.1)

#X为自变量,Y为标签,生成数据X,Y
X, Y = create_data(true_w, true_b, num)

#画图 scatter散点图
plt.scatter(X[:, 2], Y, 1)      #(自变量,标签,散点的大小);x和y必须相同大小,所以此例要对x进行切片,x为500*4,y为500*1,所以要切一列x出来,该行切的第4列

# 显示绘制的图形
plt.show()


# 假设只有数据,要通过X,Y推测w,b
# 取数据函数,每次访问这个函数,就能提供一批数据
#一批数据解读:训练模型是先随机w和b,输入x计算出预测值y,然后预测值和真实值通过损失函数算得损失,所有损失相加取平均值,通过梯度下降算法(w1=w0-学习率*损失函数对w0求偏导)训练模型。一批数据指的是不再所有损失相加取平均值算一次loss更新一次模型,而是一批数据算一次loss,然后更新一次模型。
def data_provider(data, label, batchsize):      #(数据,标签,每次取多少数据)
    length = len(label)                         #label或data都可以
    indices = list(range(length))               #把数据的个数(数字)变为一个范围,再转换成列表(即indices是0~length的列表)
    #如果只有这两行代码,那么是按顺序取数据,一般不能按顺序取数据,做不到普适性随机性,训练要求数据是随机打乱的
    random.shuffle(indices)                     #把数据打乱

    for each in range(0, length, batchsize):    #(小,大,步长)
        get_indices = indices[each: each+batchsize]     #数据16个一轮取
        get_data = data[get_indices]                    #列表嵌套列表,列表中包含另一个列表作为元素,适合表示多维数据,如矩阵,表格
        get_label = label[get_indices]                  #data,label同时取前batchsize个数据

        yield get_data, get_label               #有存档点的return。

#试运行
batchsize = 16
# for batch_x, batch_y in data_provider(X, Y, batchsize): #for循环 in后面 的返回值会给到 in 前面的变量
#     print(batch_x, batch_y)
#     break

# 定义一个模型(函数)
def fun(x, w, b):
    pred_y = torch.matmul(x, w) + b
    return pred_y

# 定义一个Loss
def maeLoss(pred_y, y):                                 #mae平均绝对误差
    return torch.sum(abs(pred_y - y)) / len(y)          #损失函数Loss,abs取绝对值

#随机梯度下降std,更新参数
def sgd(paras, lr):     #(参数,学习率)
    with torch.no_grad():                               #属于这句代码的部分不计算梯度。张量网上所有的计算都会积攒梯度,不是所有梯度我们都需要,我们只要loss对参数的梯度
        for para in paras:                              #从全部参数paras每次取一笔参数para出来
            para -= para.grad * lr                      #梯度下降,不能写成 para = para - para.grad * lr,这句相当于创建了一个新的para,报错
            para.grad.zero_()                           #梯度归零


# 设置学习率,偏置b,随机w0
lr = 0.01
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True)   #requires_grad=True这个w需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True)
print(w_0, b_0)

# 训练轮数
epochs = 50

for epoch in range(epochs):                                    #对于每一轮来说(一轮是全部数据,该例为500个)
    data_loss = 0
    for batch_x, batch_y in data_provider(X, Y, batchsize):     # 从X,Y中取batchsize数量的一批数据
        pred_y = fun(batch_x, w_0, b_0)                         #取完数据后算预测值
        loss = maeLoss(pred_y, batch_y)                         #计算loss
        loss.backward()                                         #梯度回传,w_0和b_0
        sgd([w_0, b_0], lr)                                     #梯度下降更新模型

        data_loss += loss                                       #把每一轮(500个)的loss加起来

    print("epoch %03d: loss: %.6f"%(epoch, data_loss))          #03d三位整数,.6f六位浮点数。百分号后面替换百分号前面

print("真实值:", true_w, true_b)
print("预测值:", w_0, b_0)

# 画图, 加.detach().numpy()因为数据在张量网上不能画图,所以要取下来
idx = 3
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy()*w_0[idx].detach().numpy()+b_0.detach().numpy())                  #画直线,一个x对应一个w,所以要切片
plt.scatter(X[:, idx], Y, 1)            #散点图为真实值,上一行直线为预测值
plt.show()

# 张量网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值