目录
1. 多变量线性回归
房价可能受到多个因素的影响,比如尺寸、卧室的数量、房子的层数和房龄,这是多变量线型回归的一个经典例子。
1.1 模型
假设因变量
y
y
y受
n
n
n个因素的影响,这些因素分别为
x
1
,
x
2
,
⋯
,
x
n
x_1,x_2,\cdots,x_n
x1,x2,⋯,xn。模型为
y
=
w
1
x
1
+
w
2
x
2
+
⋯
+
w
n
x
n
+
b
y=w_1x_1+w_2x_2+\cdots+w_nx_n+b
y=w1x1+w2x2+⋯+wnxn+b,代价函数为
J
(
w
1
,
w
2
,
⋯
,
w
n
,
b
)
=
1
2
m
∑
i
=
1
m
(
w
1
x
1
(
i
)
+
w
2
x
2
(
i
)
+
⋯
+
w
n
x
n
(
i
)
+
b
−
y
(
i
)
)
2
J(w_1,w_2,\cdots,w_n,b)=\displaystyle\frac{1}{2m}\sum_{i=1}^m(w_1x_1^{(i)}+w_2x_2^{(i)}+\cdots+w_nx_n^{(i)}+b-y^{(i)})^2
J(w1,w2,⋯,wn,b)=2m1i=1∑m(w1x1(i)+w2x2(i)+⋯+wnxn(i)+b−y(i))2。
如果直接以上面的公式进行计算,那么计算的代价很大。下面以向量化的方式改写上面的公式。令
w
⃗
=
[
w
1
,
w
2
,
⋯
,
w
n
]
T
,
x
⃗
=
[
x
1
,
x
2
,
⋯
x
n
]
T
\vec{w}=[w_1,w_2,\cdots,w_n]^T,\vec{x}=[x_1,x_2,\cdots\,x_n]^T
w=[w1,w2,⋯,wn]T,x=[x1,x2,⋯xn]T,则模型为
f
w
⃗
,
b
(
x
⃗
)
=
w
⃗
T
x
⃗
+
b
f_{\vec{w},b}(\vec{x})=\vec{w}^T\vec{x}+b
fw,b(x)=wTx+b,代价函数为
J
(
w
⃗
,
b
)
=
1
2
m
∑
i
=
1
m
[
f
w
⃗
,
b
(
x
⃗
(
i
)
)
−
y
(
i
)
]
2
J(\vec{w},b)=\displaystyle\frac{1}{2m}\sum_{i=1}^m[f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)}]^2
J(w,b)=2m1i=1∑m[fw,b(x(i))−y(i)]2,其中
x
⃗
(
i
)
\vec{x}^{(i)}
x(i)指的是m行样本中第i行的数据。参数是
w
⃗
和
b
\vec{w}和b
w和b。
多变量线性回归的梯度下降公式如下:
w
j
=
w
j
−
α
∂
J
(
w
⃗
,
b
)
∂
w
j
=
w
j
−
α
m
∑
i
=
1
m
x
j
(
i
)
[
f
w
⃗
,
b
(
x
⃗
(
i
)
)
−
y
(
i
)
]
b
=
b
−
α
∂
J
(
w
⃗
,
b
)
∂
b
=
b
−
α
m
∑
i
=
1
m
[
f
w
⃗
,
b
(
x
⃗
(
i
)
)
−
y
(
i
)
]
\begin{aligned} \Large w_j&=\Large w_j-\alpha\frac{\partial J(\vec{w},b)}{\partial w_j}\\ &=\Large w_j-\displaystyle\frac{\alpha}{m}\sum_{i=1}^mx_j^{(i)}[f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)}]\\ \Large b&=\Large b-\alpha\frac{\partial J(\vec{w},b)}{\partial b}\\ &=\Large b-\displaystyle\frac{\alpha}{m}\sum_{i=1}^m[f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)}] \end{aligned}
wjb=wj−α∂wj∂J(w,b)=wj−mαi=1∑mxj(i)[fw,b(x(i))−y(i)]=b−α∂b∂J(w,b)=b−mαi=1∑m[fw,b(x(i))−y(i)]
构建模型的Python代码如下:
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("deeplearning.mplstyle")
plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"] # 设置中文字体
plt.rcParams["axes.unicode_minus"] = False # 正确显示负号
class MyLinearRegression:
def __init__(self, alpha=1e-3, epochs=1e3):
self.m = None
self.w = None
self.b = 0
self.alpha = alpha
self.e = epochs
self.jwb = []
def _f(self, x):
return np.dot(x, self.w) + self.b
def _loss(self, x, y):
return np.sum((self._f(x) - y) ** 2) / (2 * self.m)
def plotlearingcurve(self, st=0, end=None):
end = int(self.e) if end is None else end
plt.figure(0)
plt.plot(np.arange(self.e + 1), self.jwb)
plt.title(f"学习率为{self.alpha}的学习曲线图")
plt.ylabel("代价函数")
plt.xlabel("迭代次数")
plt.figure(1)
plt.plot(np.arange(st, end + 1), self.jwb[st:end + 1])
plt.title(f"学习曲线图(迭代次数从{st}开始)")
def fit(self, x, y):
self.m = len(x)
self.w = np.zeros((len(x[0]), 1))
self.jwb.append(self._loss(x, y))
count = 0
while count < self.e:
w_temp = self.w - self.alpha * np.dot(x.T, self._f(x) - y) / self.m
self.b = self.b - self.alpha * np.sum(self._f(x) - y) / self.m
self.w = w_temp
self.jwb.append(self._loss(x, y))
count += 1
def predict(self, x):
return self._f(x)
def parameters(self):
return self.w, self.b
1.2 迭代次数和学习率的选择
房价预测的数据如下:
大小(平方英尺) | 卧室数量 | 层数 | 房龄 | 价格 |
---|---|---|---|---|
2104 | 5 | 1 | 45 | 460 |
1416 | 3 | 2 | 40 | 232 |
852 | 2 | 1 | 35 | 178 |
房价预测的模型为 f w ⃗ , b ( x ⃗ ) = w ⃗ T x ⃗ + b ,其中 w ⃗ = [ w 1 , w 2 , w 3 , w 4 ] T , x ⃗ = [ x 1 , x 2 , x 3 , x 4 ] T f_{\vec{w},b}(\vec{x})=\vec{w}^T\vec{x}+b,其中\vec{w}=[w_1, w_2, w_3, w_4]^T,\vec{x}=[x_1, x_2, x_3, x_4]^T fw,b(x)=wTx+b,其中w=[w1,w2,w3,w4]T,x=[x1,x2,x3,x4]T。
1.2.1 迭代次数的选择
假设 w ⃗ \vec{w} w的初值为 [ 0 , 0 , 0 , 0 ] [0, 0, 0, 0] [0,0,0,0], b b b的初值为0,学习率 α \alpha α的值为 1 0 − 7 10^{-7} 10−7,下面利用梯度下降算法进行1000次迭代,画出代价函数随迭代次数变化的图像,这个图像就是模型的学习曲线图。从下图两张图中,可以看出迭代30次后,代价函数值降低幅度变缓,因此迭代次数选择30次即可。
![]() | ![]() |
---|---|
画上述两个图的Python代码如下: |
x_train = np.array([[2104, 5, 1, 45], [1416, 3, 2, 40], [852, 2, 1, 35]]) # 特征
y_train = np.array([460, 232, 178]).reshape(3, 1) # 目标
linReg = MyLinearRegression(1e-7)
linReg.fit(x_train, y_train)
linReg.plotlearingcurve(30)
1.2.2 学习率的选择
从经验来说,学习率的值从0.001开始,如果代价函数没有下降,学习率的值要降低,变为原来的
1
3
\Large \frac{1}{3}
31倍;如果代价函数下降很慢,学习率的值要提高,一般变为原来的3倍。
学习率的值改为0.001,模型的学习曲线图如下。从下图中,可以看出代价函数的值在迭代过程中没有减小反而上升了,因此学习率需要降低,直至代价函数值降低。
下面给出学习率一路降低直至代价函数值减小的一组学习曲线图。学习率为
3
×
1
0
−
7
3\times10^{-7}
3×10−7时,代价函数值减小,不再是增大。此时,再把代价函数快速下降时的部分图像放大,观察代价函数降低幅度变缓时的迭代次数,若是迭代次数比较小,那么此时的学习率正是一个最佳的学习率;若是迭代次数比较大,则在保持学习率量级的情况下,稍微把学习率提升一点。如果提升后的学习率使代价函数降低幅度变缓时的迭代次数比较小的话,那么此时的学习率就是我们应该选择的学习率。
![]() | ![]() |
---|---|
![]() | ![]() |
![]() | ![]() |
![]() |
2. 多项式回归
因变量
y
y
y可能只与一个因素x有关,但两者之间的关系不是线性的,因此需要以x的多项式来拟合
y
y
y。x的多项式最高次数要根据实际数据选择。多项式回归的本质还是多变量线性回归,输入特征由多个不同的特征变为一个特征的不同幂次方,比如
x
、
x
2
、
x
3
x、x^2、x^3
x、x2、x3。
给出一些数据,如
y
=
x
2
y=x^2
y=x2上
x
=
1
,
2
,
⋯
,
10
x = 1, 2, \cdots, 10
x=1,2,⋯,10对应的这10个点,来拟合曲线
y
=
w
0
x
+
w
1
x
2
+
w
2
x
3
+
b
y=w_0x+w_1x^2+w_2x^3+b
y=w0x+w1x2+w2x3+b。令特征
z
⃗
=
[
x
,
x
2
,
x
3
]
T
\vec{z}=[x, x^2, x^3]^T
z=[x,x2,x3]T,
w
⃗
=
[
w
0
,
w
1
,
w
2
]
T
\vec{w}=[w_0, w_1, w_2]^T
w=[w0,w1,w2]T,则
y
=
w
⃗
T
z
⃗
+
b
y=\vec{w}^T\vec{z}+b
y=wTz+b,这样就把多项式回归化成了多变量线性回归。实际值与预测值的图像如下:
画出上图的Python代码如下:
x = np.arange(20)
y = x ** 2
y = y.reshape(20, 1)
x1 = np.c_[x, x ** 2, x ** 3]
x1_normalized = (x1 - np.mean(x1, axis=0)) / np.std(x1, axis=0)
linReg = MyLinearRegression(1e-1, 1e4)
linReg.fit(x1_normalized, y)
plt.scatter(x, y, marker='x', zorder=2, label="实际值")
plt.plot(x, linReg.predict(x1_normalized), c="red", zorder=1, label="预测值")
plt.legend()
3. 简单介绍特征工程
特征工程需要从原始数据中提取、构建和选择特征,以便提高机器学习模型的性能。下面简单介绍特征工程中的一些内容:
3.1 特征选择
特征需要选择最有信息量的特征,可以通过使用统计测试、模型选择或基于知识的技术来选择与目标变量最相关的特征。此外,还需要去除冗余特征,删除那些与其他特征高度相关或提供重复信息的特征。
3.2 特征提取
特征提取从原始数据中提取有用的信息,比如从文本中提取词频,从时间序列中提取趋势和季节性成分。
3.3 特征构建
特征构建需要创建新特征,通过组合现有特征或应用数学变换来构造新的特征。
3.4 特征缩放
特征缩放能把特征缩放到指定的范围,从而达到以下几个目的:1. 提升机器学习算法的性能 2. 加快算法学习的速度 3. 避免数值的不稳定性 4. 提升模型的泛化能力 5. 更容易解释模型的权重
要根据数据的特性和机器学习算法选择合适的特征缩放方法!下面简单介绍其中两种特征缩放方法。
3.4.1 最大-最小归一化
最大-最小归一化把特征的范围缩放到 [ 0 , 1 ] [0, 1] [0,1],公式为 x ′ = x − x m i n x m a x − x m i n x'=\Large \frac{x-x_{min}}{x_{max}-x_{min}} x′=xmax−xminx−xmin。
3.4.2 Z-Score归一化
Z-Score归一化把特征缩放到均值为0,标准差为1的分布,公式为 x ′ = x − μ σ x'=\Large \frac{x-\mu}{\sigma} x′=σx−μ,其中 μ \mu μ是特征的均值, σ \sigma σ是特征的标准差。
3.4.3 用Z-Score归一化方法后进行房价预测
学习率的值为
0.3
0.3
0.3,
w
⃗
\vec{w}
w的初值为
[
0
,
0
,
0
,
0
]
[0, 0, 0, 0]
[0,0,0,0],
b
b
b的初值为0。先对特征进行Z-Score归一化后,再对模型进行训练画出学习曲线图。从下图中,可以看出迭代次数为15时,代价函数值降低幅度变缓。与上面没有归一化需要迭代30次相比,归一化后再进行训练,算法收敛更快。
画出上图的Python代码如下:
x_train_normalized = (x_train - np.mean(x_train, axis=0)) / np.std(x_train, axis=0)
linReg = MyLinearRegression(0.3)
linReg.fit(x_train_normalized, y_train)
linReg.plotlearingcurve(15, 100)
4. 使用scikit-learn进行线性回归和多项式回归
4.1 使用scikit-learn进行线性回归
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 生成训练数据
np.random.seed(0)
x = np.random.rand(100, 1)
y = np.random.rand(100, 1)
LinReg = LinearRegression() # 构建模型
LinReg.fit(x, y) # 拟合模型
print(mean_squared_error(y, LinReg.predict(x))) # 均方误差
4.2 使用scikit-learn进行多项式回归
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
# 生成训练数据
np.random.seed(1)
x = np.random.rand(100, 1) * 2
y = np.power(x, 3) + np.random.rand(100, 1) * 0.4
# 生成多项式特征
poly = PolynomialFeatures(degree=3)
# 创建线性回归模型
LinReg = LinearRegression()
# 创建管道,连接多项式特征生成器和线性回归模型
pipe = make_pipeline(poly, LinReg)
pipe.fit(x, y) # 拟合数据
print(mean_squared_error(y, pipe.predict(x))) # 均方误差
参考
吴恩达 机器学习视频