机器学习
Overview
机器学习其实就是一种最优化问题——给定约束,最优化目标函数。简单来讲,在机器学习中,基于已知数据,假设数据之间存在某种关联,我们想要尽可能接近地找到这种关联。在这里,约束就是已知数据,目标函数则为“模型”和“真实”的差距。从数学的角度,这个问题可以这样表述:
- 假设我们的模型可以表示为。
- 可以是任意的函数,是参数向量,有些地方也把它叫做权重(weights),因为假如是一个线性模型,就是权重一个直观的表示。总之叫参数也好,系数或者权重也好,表达的都是一个东西,只是叫法不同。
- 此外我们定义一个合理的损失函数Loss Function:。损失函数表示“模型”和“真实”的差距。在确定模型表达形式后,我们的目标实际上就是找到权重向量,使得期望损失达到最小:
监督学习(Supervised Learning)
在监督学习下,我们有一组训练集,训练集中数据可分为输入(input)和输出(output)。假设和之间存在某个函数关系使得。也就是说,我们可以通过某一种方式,输入后可以得到。
因此,监督学习的问题可以表示为最小化期望损失:
其中为损失函数。
假设我们不存在训练集,没有输入输出数据,这个问题也就被一般化为无监督学习(Unsupervised Learning)。
Recall:统计学模型——最小二乘估计(OLS)
当我们做OLS线性回归模型时,给定因变量和自变量,我们可以得到线性模型:
其中
该问题的的目标是最小化残差平方和(RSS):
得到:
其实这也是一个简单的机器学习问题:
- 损失函数:
- 模型:
机器学习的简单实践
- 我们假设。
- 此时,。
- 理论上和存在基于以上形式的二次关系。
- 我们现在随机生成一组数据$:
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as opt
def F(x):
return x**2 + 2*x + 3
xs = np.random.uniform(-6, 4, 20)
ys = [F(x) + np.random.normal(0,2) for x in xs]
data = (xs, ys)
我们看看随机生成的点的分布情况
domain = np.linspace(-6,4,50)
fig, ax = plt.subplots(figsize = (8,6))
ax.plot(domain, F(domain), label='Theoretical Model')
ax.scatter(xs, ys, c='r', marker='x', label='Data')
plt.legend()
现在我们不知道原本的函数关系,只已知这些数据,怎么去拟合这个函数?这就是机器学习中的一个简单问题。
fig, ax = plt.subplots(figsize = (8,6))
ax.scatter(xs, ys, c='r', marker='x', label='Data')
plt.legend()
函数我们可以假设成任意的形式,因为基于泰勒展开原理,任何一个函数都可以展开成一个多项式的形式。因此我们函数的也理所当然地从多项式开始入手,可以是一次,可以是二次甚至更高次。
def F_hat_o1(x, w):
(a, b) = w
return a*x + b
def F_hat_o2(x, w):
(a, b, c) = w
return a*x**2 + b*x + c
def F_hat_o4(x, w):
(a, b, c, d, e) = w
return a*x**4 + b*x**3 + c*x**2 + d*x + e
定义损失函数:
def L(w):
predicted_data = np.array([F_hat(x, w) for x in data[0]])
training_data = np.array(data[1])
return np.sum((training_data - predicted_data) ** 2)
一阶:
initial_weights = [0., 0.]
F_hat = F_hat_o1
final_weights = opt.minimize(L, initial_weights)
weights_o1 = final_weights.x
print(weights_o1)
[ 0.46082929 10.87317174]
二阶:
initial_weights = [0., 0., 0.]
F_hat = F_hat_o2
final_weights = opt.minimize(L, initial_weights)
weights_o2 = final_weights.x
print(weights_o2)
[0.99123066 1.94480201 2.41571896]
四阶:
initial_weights = [0., 0., 0., 0., 0.]
F_hat = F_hat_o4
final_weights = opt.minimize(L, initial_weights)
weights_o4 = final_weights.x
print(weights_o4)
[-0.0155209 -0.05878026 1.28288611 2.52211275 1.32693671]
def F_hat(x, weights, order):
xs = np.array([x**i for i in range(order,-1,-1)])
weights = np.array(weights)
y_hat = np.sum(np.array(xs.T*weights.T), axis=1)
return y_hat
F_o1 = lambda x: F_hat(x, weights_o1, 1)
F_o2 = lambda x: F_hat(x, weights_o2, 2)
F_o4 = lambda x: F_hat(x, weights_o4, 4)
domain = np.linspace(-6,4,50)
fig, ax = plt.subplots(figsize = (8,6))
ax.plot(domain, F(domain), label='Theoretical Model')
ax.plot(domain, F_o1(domain), label='1st order')
ax.plot(domain, F_o2(domain), label='2nd order')
ax.plot(domain, F_o4(domain), label='4th order')
ax.scatter(xs, ys, c='r', marker='x', label='Data')
plt.legend()
虽然4阶的模型能够让数据点更紧密地落在曲线上,但实际上因为阶数过高而过拟合了,效果并没有二阶模型好。