前言
本文是基于《机器学习实战》和吴恩达的ML课程自己的总结,也包括作业代码的重写和注释。
一、线性回归
1.定义
线性回归假设特征和结果满足线性关系。每个特征对结果的影响都可以通过特征前的参数体现,且每个特征变量可以先映射到一个函数,然后再参与线性计算。从而表达特征与结果之间的非线性关系。
如果用
x
1
x_1
x1,
x
2
x_2
x2…
x
n
x_n
xn描述特征,就可以通过以下函数做出估计:
这里的θ表示了每个特征的重要性,如果令x0=1就可以用向量来表示此函数:
为了评估算出来的θ是否合适,我们用损失(错误)函数来描述拟合程度:
2.θ的计算
梯度下降
为了确定θ的值,用梯度下降来使函数向J(θ)也就是损失函数下降最快的方向走,从而求得全局最小值。哪个点向上,我们就向反方向下坡,所以我们可以更新J(θ):
梯度下降的方法一般有:
- 批量梯度下降:在计算梯度下降的每一步时,都是基于完整的训练集X的。且可以找到全局最小值,只是用的时间比较长。
- 随机梯度下降:每一步在训练集中随机选择一个实例,且仅基于该实例来计算梯度,其在达到最小值之后也会不断反弹,此时不断降低学习率从而尽可能接近全局最小值。
- 小批量梯度下降:在小批量的随机实例集上计算梯度,在参数空间中更稳定,其在最终比随机梯度下降更接近最小值,但其可能很难摆脱局部最小值。
最小二乘法
也是确定θ的方法之一,将训练特征表示为X矩阵,结果表示为y向量,从而得出θ:
3.带权重的线性回归
带权重的线性回归加入了权重,此算法是假设离要预测的特征越近影响越大,越远越小,从而可以应用于非参数学习。
其中
w
(
i
)
w^{(i)}
w(i)符合公式:
二、逻辑回归
1.定义
一般来说回归不会被用于分类,因为回归是连续型模型,且受噪声影响较大,如果必须使用,可以使用对数回归,即在特征到结果的映射中加入了一层函数映射,先把特征线性求和,然后使用函数g(z)做运维假设函数来预测,g(z)可以将连续值映射到0和1上。
此时的回归方程:
其中g(z):
所以就可以实现用回归来进行二值分类,假设二值回归符合伯努利分布,即:
他的损失函数为:
其实与线性回归类似,只是将
θ
T
X
(
i
)
\theta^TX^{(i)}
θTX(i)通过g(z)映射到
h
θ
(
x
(
i
)
)
h_\theta\left(x\left(i\right)\right)
hθ(x(i))
2.Softmax回归
是将逻辑回归推广到多分类问题,对于一个给定的实例x,Softmax回归首先计算出每个类k的分数 s k ( x ) s_k(x) sk(x),然后将这些分数应用softmax(归一化)函数,从而估算出每个类的概率。
对于某个类k:
s
k
(
x
)
=
x
T
θ
(
k
)
s_k(x)=x^T\theta^{(k)}
sk(x)=xTθ(k)
softmax函数:
p
^
k
=
e
x
p
(
s
k
(
x
)
)
/
∑
i
=
1
k
e
x
p
(
s
j
(
x
)
)
{\widehat p}_k=exp(s_k(x))/\sum_{i=1}^kexp(s_j(x))
p
k=exp(sk(x))/∑i=1kexp(sj(x))
交叉熵
用于衡量一组估算出的类概率跟目标类的匹配程度。
下面给出交叉熵:
J
(
⊙
)
=
−
1
/
m
(
∑
i
=
1
m
∑
k
=
1
K
y
k
(
i
)
l
o
g
(
p
^
k
(
i
)
)
)
J(\odot)=-1/m(\sum_{i=1}^m\sum_{k=1}^Ky_k^{(i)}l\mathrm{og}(\widehat p_k^{(i)}))
J(⊙)=−1/m(∑i=1m∑k=1Kyk(i)log(p
k(i)))
也是softmax回归函数的成本函数。
下面给出类k的交叉熵梯度向量:
∇
θ
(
k
)
J
(
⊙
)
=
1
/
m
(
∑
i
=
1
m
(
p
^
k
(
i
)
−
y
k
(
i
)
)
x
(
i
)
)
\nabla_{\theta(k)}J(\odot)=1/m(\sum_{i=1}^m(\widehat p_{k\;}^{(i)}-y_k^{(i)})x^{(i)})
∇θ(k)J(⊙)=1/m(∑i=1m(p
k(i)−yk(i))x(i))
三、练习
用softmax进行批量梯度下降,实现提前停止法
1.数据导入
from sklearn import datasets
iris = datasets.load_iris()
list(iris.keys())
#取data的2,3列,即为花瓣的长度和宽度来预测
X = iris["data"][:,(2,3)]
y = iris["target"]
#np.c_列结合,所有的x0=1
import numpy as np
X_with_bias = np.c_[np.ones([len(X),1]),X]
#打乱output方便复用
np.random.seed(2042)
#分成训练集、验证集、测试集
test_ratio = 0.2
validation_ratio = 0.2
total_size = len(X_with_bias)
test_size = int(total_size*test_ratio)
validation_size = int(total_size*validation_ratio)
train_size = total_size-test_size-validation_size
rnd_indices = np.random.permutation(total_size)#np.random.permutation()为0-total_size之间的序列进行随机排序
X_train = X_with_bias[rnd_indices[:train_size]]
y_train = y[rnd_indices[:train_size]]
X_valid = X_with_bias[rnd_indices[train_size:-test_size]]
y_valid = y[rnd_indices[train_size:-test_size]]
X_test = X_with_bias[rnd_indices[-test_size:]]
y_test = y[rnd_indices[-test_size:]]
#onehot编码,为了方便训练softmax回归模型
def to_one_hot(y):
n_classes = y.max() + 1
m = len(y)
Y_one_hot = np.zeros((m, n_classes))
Y_one_hot[np.arange(m),y] = 1
return Y_one_hot
Y_train_one_hot = to_one_hot(y_train)
Y_valid_one_hot = to_one_hot(y_valid)
Y_test_one_hot = to_one_hot(y_test)
2.定义softmax函数
def softmax(logits):
exps = np.exp(logits)
exp_sum = np.sum(exps, axis=1, keepdims=True)
return exps/exp_sum
3.定义输入输出
#定义输入输出数量
n_inputs = X_train.shape[1] #两个特征及偏置项
n_outputs = len(np.unique(y_train)) #对应3种分类
4.训练模型
#训练softmax回归模型,加入l2正则化和停止标志
eta = 0.1
n_iterations = 5001
m = len(X_train)
epsilon = 1e-7
alpha = 0.1 #正则化超参数
best_loss = np.infty
Theta = np.random.randn(n_inputs, n_outputs)
for iteration in range(n_iterations):
logits = X_train.dot(Theta)
Y_proba = softmax(logits)
xentropy_loss = -np.mean(np.sum(Y_train_one_hot * np.log(Y_proba+epsilon), axis=1))
l2_loss = 1/2 * np.sum(np.square(Theta[1:]))
loss = xentropy_loss + alpha * l2_loss
error = Y_proba - Y_train_one_hot
gradients = 1/m * X_train.T.dot(error) + np.r_[np.zeros([1, n_outputs]), alpha*Theta[1:]]
Theta = Theta - eta*gradients
logits = X_valid.dot(Theta)
Y_proba = softmax(logits)
xentropy_loss = -np.mean(np.sum(Y_valid_one_hot * np.log(Y_proba+epsilon), axis=1))
l2_loss = 1/2 * np.sum(np.square(Theta[1:]))
loss = xentropy_loss + alpha * l2_loss
if iteration%500 == 0:
print(iteration, loss)
if loss < best_loss:
best_loss = loss
else:
print(iteration-1, best_loss)
print(iteration, loss, "early stopping")
break
5.验证结果
#验证
logits = X_valid.dot(Theta)
Y_proba = softmax(logits)
y_predict = np.argmax(Y_proba, axis=1)
accuracy_score = np.mean(y_predict == y_valid)
accuracy_score
等于1.0
#最后验证在测试集上效果
logits = X_test.dot(Theta)
Y_proba = softmax(logits)
y_predict = np.argmax(Y_proba, axis=1)
accuracy_score = np.mean(y_predict == y_test)
accuracy_score
约等于0.93