线性回归原理与python实现

线性回归原理:

        在一堆散点中 xi yi,拟合出一个函数使其离所有点最近

        目标函数:y = w1x + w0

        误差函数:MSE(均方误差) L(w1,w0)= Σ(yi - y)^2

        优化方法:梯度下降,autograd,反向传播,优化公式,进行更新

        公式更新:wt+1 = wt-dL/dwt *δ

乘积的意义:将梯度乘以学习率,得到的结果是参数更新的大小。如果梯度较大,乘以一个较小的学习率可以使参数更新的幅度减小,保持在一个合理的范围内。这样,我们可以沿着损失函数下降最快的方向移动,同时避免更新步长过大导致跳过最优解。所以,乘以一个很小的数(学习率)可以控制参数更新的幅度,确保梯度下降算法朝着最小化损失函数的方向稳定地进行。

import matplotlib.pyplot as plt
import torch
import matplotlib.pyplot as pit

# 点对
x = torch.tensor([1.4,5,11,16,21])
y = torch.tensor([14.4,29.6,62,85.5,113.4])
# 绘制散点图
plt.scatter(x.numpy(),y.numpy())
plt.show()


def produce_x(x):
    x0 = torch.ones(x.numpy().size)
    X = torch.stack((x,x0),dim=1)
    return X

X = produce_x(x)
print(X)

inputs = X
target = y
w = torch.rand(2,requires_grad=True)
print(w)

def train(epoch = 100,lr = 0.01,num = 100000):
    for epoch in range(epoch):
        output = inputs.mv(w)
        loss = (output - target).pow(2).sum()/num

        loss.backward()
        w.data -= lr * w.grad
        # 清空w的梯度,不然会累加
        w.grad.zero_()
        if  epoch%80 == 0:
            draw(output,loss)

    return w,loss

def draw(output,loss):
    if CUDA:
        output = output.cpu()
    # 清空画布
    plt.cla()
    plt.scatter(x.numpy(), y.numpy())
    plt.plot(x.numpy(),output.data.numpy(),'r-',lw=5)
    plt.text(0.5,0,'loss=%s'%(loss.item()),fontdict={'size':20,'color':'red'})
    plt.pause(0.005)


# 训练
# w,loss = train(10000,lr=0.0001)
# print("loss:",loss.item())
# print("weights:",w.data)

# 上述我们使用的是produce_X来初始化五个预设值
# 我们可以用它来生成许多数据并初始化

x = torch.linspace(-3,3,100000)
X = produce_x(x)
y = x +1.2*torch.rand(x.size())
w = torch.rand(2)

plt.scatter(x.numpy(),y.numpy(),s=0.001)
plt.show()

# cuda加速
CUDA = 1
if CUDA:
    inputs = X.cuda()
    target = y.cuda()
    w = w.cuda()
    w.requires_grad = True
else:
    inputs = X
    target = y
    w = w
    w.requires_grad = True

num1 = target.numel()
w,loss = train(10000,lr=0.0001,num=num1)

print("loss:",loss.item())
print("weights:",w.data)

 

 下面的实现我们用pytorch的库来实现

import matplotlib.pyplot as plt
import torch
from torch import nn,optim
from time import perf_counter

# 增加一个维度100000行1列
x = torch.unsqueeze(torch.linspace(-3,3,100000),dim=1)
y = x + 1.2*torch.rand(x.size())

def draw(output,loss):
    if CUDA:
        output = output.cpu()
    # 清空画布
    plt.cla()
    plt.scatter(x.numpy(), y.numpy())
    plt.plot(x.numpy(),output.data.numpy(),'r-',lw=5)
    plt.text(0.5,0,'loss=%s'%(loss.item()),fontdict={'size':20,'color':'red'})
    plt.pause(0.005)


class LR(nn.Module):
    def __init__(self):
        super(LR,self).__init__()
        self.linear = nn.Linear(1,1)

    def forward(self,x):
        out = self.linear(x)
        return out

CUDA = torch.cuda.is_available()
if CUDA:
    LR_model = LR().cuda()
    inputs = x.cuda()
    target = y.cuda()
else:
    LR_model = LR()
    inputs = x
    target = y

criterion = nn.MSELoss()
optimizer = optim.SGD(LR_model.parameters(),lr=1e-4)

def Train(model,criterion,optimizer,epochs):
    for epochs in range(epochs):

        output = model(inputs)
        loss = criterion(output,target)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step() #权重更新
        if epochs % 80 == 0:
            draw(output,loss)
    return model,loss


START = perf_counter()
LR_model,loss = Train(LR_model,criterion,optimizer,10000)
FINISH = perf_counter()
time = FINISH - START
print("time:%s" % time)
print("loss:",loss.item())
print("weights:",list(LR_model.parameters()))





你可能感兴趣的:(python,线性回归,算法)