哈工大2022机器学习实验一:曲线拟合
Posted Castria
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈工大2022机器学习实验一:曲线拟合相关的知识,希望对你有一定的参考价值。
这个实验的要求写的还是挺清楚的(与上学期相比),本博客采用python实现,科学计算库采用numpy
,作图采用matplotlib.pyplot
,为了简便在文件开头import如下:
import numpy as np
import matplotlib.pyplot as plt
本实验用到的numpy函数
一般把numpy
简写为np
(import numpy as np)。下面简单介绍一下实验中用到的numpy函数。下面的代码均需要在最前面加上import numpy as np
。
np.array
该函数返回一个numpy.ndarray
对象,可以理解为一个多维数组(本实验中仅会用到一维(可以当作列向量)和二维(矩阵))。下面用小写的
x
\\pmb x
xx表示列向量,大写的
A
A
A表示矩阵。A.T
表示
A
A
A的转置。对ndarray
的运算一般都是逐元素的。
>>> x = np.array([1,2,3])
>>> x
array([1, 2, 3])
>>> A = np.array([[2,3,4],[5,6,7]])
>>> A
array([[2, 3, 4],
[5, 6, 7]])
>>> A.T # 转置
array([[2, 5],
[3, 6],
[4, 7]])
>>> A + 1
array([[3, 4, 5],
[6, 7, 8]])
>>> A * 2
array([[ 4, 6, 8],
[10, 12, 14]])
np.random
np.random
模块中包含几个生成随机数的函数。在本实验中用随机初始化参数(梯度下降法),给数据添加噪声。
>>> np.random.rand(3, 3) # 生成3 * 3 随机矩阵,每个元素服从[0,1)均匀分布
array([[8.18713933e-01, 5.46592778e-01, 1.36380542e-01],
[9.85514865e-01, 7.07323389e-01, 2.51858374e-04],
[3.14683662e-01, 4.74980699e-02, 4.39658301e-01]])
>>> np.random.rand(1) # 生成单个随机数
array([0.70944563])
>>> np.random.rand(5) # 长为5的一维随机数组
array([0.03911319, 0.67572368, 0.98884287, 0.12501456, 0.39870096])
>>> np.random.randn(3, 3) # 同上,但每个元素服从N(0, 1)(标准正态)
数学函数
本实验中只用到了np.sin
。这些数学函数是对np.ndarray
逐元素操作的:
>>> x = np.array([0, 3.1415, 3.1415 / 2]) # 0, pi, pi / 2
>>> np.round(np.sin(x)) # 先求sin再四舍五入: 0, 0, 1
array([0., 0., 1.])
此外,还有np.log
、np.exp
等与python的math
库相似的函数(只不过是对多维数组进行逐元素运算)。
np.dot
返回两个矩阵的乘积。与线性代数中的矩阵乘法一致。要求第一个矩阵的列等于第二个矩阵的行数。特殊地,当其中一个为一维数组时,形状会自动适配为 n × 1 n\\times1 n×1或 1 × n . 1\\times n. 1×n.
>>> x = np.array([1,2,3]) # 一维数组
>>> A = np.array([[1,1,1],[2,2,2],[3,3,3]]) # 3 * 3矩阵
>>> np.dot(x,A)
array([14, 14, 14])
>>> np.dot(A,x)
array([ 6, 12, 18])
>>> x_2D = np.array([[1,2,3]]) # 这是一个二维数组(1 * 3矩阵)
>>> np.dot(x_2D, A) # 可以运算
array([[14, 14, 14]])
>>> np.dot(A, x_2D) # 行列不匹配
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (3,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
np.eye
np.eye(n)
返回一个n阶单位阵。
>>> A = np.eye(3)
>>> A
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
线性代数相关
np.linalg
是与线性代数有关的库。
>>> A
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
>>> np.linalg.inv(A) # 求逆(本实验不考虑逆不存在)
array([[1. , 0. , 0. ],
[0. , 0.5 , 0. ],
[0. , 0. , 0.33333333]])
>>> x = np.array([1,2,3])
>>> np.linalg.norm(x) # 返回向量x的模长(平方求和开根号)
3.7416573867739413
>>> np.linalg.eigvals(A) # A的特征值
array([1., 2., 3.])
生成数据
生成数据要求加入噪声(误差)。上课讲的时候举的例子就是正弦函数,我们这里也采用标准的正弦函数 y = sin x . y=\\sin x. y=sinx.(加入噪声后即为 y = sin x + ϵ , y=\\sin x+\\epsilon, y=sinx+ϵ,其中 ϵ ∼ N ( 0 , σ 2 ) \\epsilon\\sim N(0, \\sigma^2) ϵ∼N(0,σ2),由于 sin x \\sin x sinx的最大值为 1 1 1,我们把误差的方差设小一点,这里设成 1 25 \\frac125 251)。
'''
返回数据集,形如[[x_1, y_1], [x_2, y_2], ..., [x_N, y_N]]
保证 bound[0] <= x_i < bound[1].
- N 数据集大小, 默认为 100
- bound 产生数据横坐标的上下界, 应满足 bound[0] < bound[1], 默认为(0, 10)
'''
def get_dataset(N = 100, bound = (0, 10)):
l, r = bound
# np.random.rand 产生[0, 1)的均匀分布,再根据l, r缩放平移
# 这里sort是为了画图时不会乱,可以去掉sorted试一试
x = sorted(np.random.rand(N) * (r - l) + l)
# np.random.randn 产生N(0,1),除以5会变为N(0, 1 / 25)
y = np.sin(x) + np.random.randn(N) / 5
return np.array([x,y]).T
产生的数据集每行为一个平面上的点。产生的数据看起来像这样:
隐隐约约能看出来是个正弦函数的形状。产生上面图像的代码如下:
dataset = get_dataset(bound = (-3, 3))
# 绘制数据集散点图
for [x, y] in dataset:
plt.scatter(x, y, color = 'red')
plt.show()
最小二乘法拟合
下面我们分别用四种方法(最小二乘,正则项/岭回归,梯度下降法,共轭梯度法)以用多项式拟合上述干扰过的正弦曲线。
解析解推导
简单回忆一下最小二乘法的原理:现在我们想用一个
m
m
m次多项式 以上是关于哈工大2022机器学习实验一:曲线拟合的主要内容,如果未能解决你的问题,请参考以下文章
f
(
x
)
=
w
0
+
w
1
x
+
w
2
x
2
+
.
.
.
+
w
m
x
m
f(x)=w_0+w_1x+w_2x^2+...+w_mx^m
f(x)=w0+w1x+w2x2+...+wmxm
来近似真实函数
y
=
sin
x
.
y=\\sin x.
y=sinx.我们的目标是最小化数据集
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
(x_1,y_1),(x_2,y_2),...,(x_N,y_N)
(x1,y1),(x2,y2),...,(xN,yN)上的损失
L
L
L(loss),这里损失函数采用平方误差:
L
=
∑
i
=
1
N
[
y
i
−
f
(
x
i
)
]
2
L=\\sum\\limits_i=1^N[y_i-f(x_i)]^2
L=i=1∑N[yi−f(xi)]2
为了求得使均方误差最小(因此最贴合目标曲线)的参数
w
0
,
w
1
,
.
.
.
,
w
m
,
w_0,w_1,...,w_m,
w0,w1,...,wm,我们需要分别求损失
L
L
L关于
w
0
,
w
1
,
.
.
.
,
w
m
w_0,w_1,...,w_m
w0,w1,...,wm的导数。为了方便,我们采用线性代数的记法:
X
=
(
1
x
1
x
1
2
⋯
x
1
m
1
x
2
x
2
2
⋯
x
2
m
⋮
⋮