机器学习简单来讲可以分为两个问题,我们都是希望能将现实中的问题进行抽象来构建数学模型,根据预测的内容,可以将问题分为回归问题和分类问题,如果预测的是连续值
,那么就是回归问题,如果预测的是离散值
,那么就是分类问题。比如房价的预测就是一个典型的回归问题,给出房子的面积、地理位置等基本输入,模型可以根据这些输入得到房子大概的价格。
原理介绍
?什么是模型
大概从大一开始,就接触到模型这个概念,很多时候不不是很清楚到底啥是个模型。以为现在的理解来看,模型就是数学公式,比如我们高中学到的kx+b就是一个线性模型,在具体的问题中,不仅要有这个公式的一般形式,而且还要有根据这个具体问题所解得得k和b的具体的值,就是现在的深度学习中,模型也可以这么理解,不过是公式更加复杂,需要求解的参数也越多而已。
线性回归的基本要素
回归问题中,以刚才所提到的房价预测为例,我们将影响房价的几个因素记为x,将成交价记为y,则这个问题可以抽线为下列公式。
y
=
w
1
x
1
+
w
2
x
2
+
w
3
x
3
+
b
y = w_1x_1 + w_2x_2 + w_3x_3 +b
y=w1x1+w2x2+w3x3+b
权重和偏差就是我们这个机器学习的模型需要学习得到的参数,学习的是大量的真实房屋数据的样本。通过大量真实的有成交价的房屋数据来进行学习,这个成为监督学习,也就是常说的supervisor learning。
线性回归的表示方法
我们将上述问题进一步抽象,得到线性回归问题的一般表示形式。
-
给定n维的输入 x = [ x 1 , x 2 , . . . , x 3 ] T x=[x_1, x_2,...,x_3]^T x=[x1,x2,...,x3]T
-
线性模型有一个n维的权重和一个标量误差
w = [ w 1 , w 2 , . . . , w n ] T , b w = [w_1,w_2,...,w_n]^T, b w=[w1,w2,...,wn]T,b -
输出是输入的加权和
y = w 1 x 1 + w 2 x 2 + . . . + w n x n + b y = w_1x_1 + w_2x_2 + ... + w_nx_n + b y=w1x1+w2x2+...+wnxn+b
向量版本为:$ y = <w, x> + b $
使用图形可以表示为下列的形式,可以看作是单层的神经网络
如何求解
求解的过程和我们参加高考的过程是一样的,我们需要事先做大量的习题,训练一个会做高考题的大脑,不断提升自我,才能完成最后的高考。模型训练的过程可以分为下面几步:
-
计算损失
回归问题比较简单,我们一般使用平方损失即可$l(y,\hat{y}) = \frac{1}{2}(y - \hat{y})^2 $
-
训练数据
搜集大量的真实房屋数据,输入模型进行学习,一般为了防止过拟合,采用
batch
来进行训练 -
参数学习
线性回归可以求得显式解,但是比较麻烦,所以一般使用随机梯度下降
sgd
(链式法则)来求解
代码实现
我们生成一个大小为2的数据,然后通过这个数据求w1,w2和b,代码是借助pytorch来实现的,构建模型的方法非常简单,只需要通过torch.Linear(2, 1)来构建一个输入为2,输出为1的全连接层即可。
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn
# 1. 生成数据集
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
# 调用框架中的API来读取数据集
def load_array(data_arrays, batch_size, is_train=True):
"""构造一个PyTorch数据迭代器。"""
dataset = data.TensorDataset(*data_arrays)
# 使用Pytorch中的dataLoader可以构造数据集加载器,迭代器的形式返回批量的数据
return data.DataLoader(dataset, batch_size, shuffle=is_train)
batch_size = 10
data_iter = load_array((features, labels), batch_size)
print(next(iter(data_iter)))
# 2. 构造模型
net = nn.Sequential(nn.Linear(2, 1))
# 初始化模型参数,不过一般pytorch模型中有个默认的初始化方式,不初始化也没问题
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
# 3. 设置损失函数,损失函数计算得到的是个标量
loss = nn.MSELoss()
# 4. 设置优化器,我们优化的是网络的参数,并且设定一个优化的学习率
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
# 5. 开始训练
num_epochs = 5
for epoch in range(num_epochs):
for X, y in data_iter:
l = loss(net(X), y)
trainer.zero_grad() # 梯度清零
l.backward() # 反向传播计算梯度
trainer.step() # 梯度下降优化权重参数
l = loss(net(features), labels)
print(f'epoch {epoch + 1}, loss {l:f}')
# 模型保存: torch.save() 可以全部保存然后直接加载,也可以只保存参数,然后初始化模型之后加载参数
# 6. 模型验证
w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)
输出如下:
可以看到误差在不断下降,由于数据比较简单,模型在第二轮就基本达到最优。
线性回归实战-房价预测
点赞超过30,我们更新kaggle房价预测的内容,也欢迎大家关注我的b站账号,会不定时地更新一些深度学习的干货视频,感谢大家的支持!