吴恩达机器学习笔记

吴恩达机器学习课程笔记

基本概念

监督学习:监督学习指的就是我们给学习算法一个数据集。这个数据集由“正确答案”组成
分类:我们试着推测出离散的输出值
回归:我们在试着推测出这一系列连续值属性
无监督学习:无监督学习中没有任何的标签,别的都不知道,就是一个数据集

监督学习

线性回归

模型表示

1.线性模型 :hθ (x)=θT X=θ0 x01 x12 x2+…+θn xn
注意:其中X=[x0,x1,x2…,xn]为n+1维特征向量,x0=1

2.多项式模型(举例):hθ (x)=θ01 x12 x223 x33+…+θnxnn
注意:我们在该模型中,我们可以令:
x2=x22 ,x3=x33…,从而将模型转化为线性回归模型
也要主要做特征缩放

代价函数

均方代价函数 J ( θ 0 , θ 1 , . . . , θ n ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J({{\theta }_{\text{0}}},{{\theta }_{1}},...,{{\theta }_{n}})=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{({{h}_{\theta }}({{x}^{(i)}})-{{y}^{(i)}})}^{2}}} J(θ0,θ1,...,θn)=2m1i=1m(hθ(x(i))y(i))2
注意:其中x(i) 代表第i个具有n+1维特征的向量

正则化均方代价函数
J ( θ 0 , θ 1 , . . . , θ n ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 + λ 2 m ∑ j = 1 n θ j 2 J({\theta _{\rm{0}}},{\theta _1},...,{\theta _n}) = \frac{1}{{2m}}\sum\limits_{i = 1}^m {{{({h_\theta }({x^{(i)}}) - {y^{(i)}})}^2}} + \frac{\lambda }{{2m}}\sum\limits_{j = 1}^n {{\theta _j}^2} J(θ0,θ1,...,θn)=2m1i=1m(hθ(x(i))y(i))2+2mλj=1nθj2

梯度下降

思想
开始时我们随机选择一个参数的组合(θ01,…,θn ),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到到到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。

算法:
θ j = θ j − α J ( θ 0 , . . . , θ n ) ∂ θ j , j = 0 , 1... n {\theta _j} = {\theta _j} - \alpha \frac{{J({\theta _{0,...,}}{\theta _n})}}{{\partial {\theta _j}}},j=0,1...n θj=θjαθjJ(θ0,...,θn)j=0,1...n
α:学习率
理解:
α:它决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大。

梯度下降算法的每次迭代受到学习率的影响:
学习率a过小,则达到收敛所需的迭代次数会非常高;
学习率a过大,每次迭代可能不会减小代价函数,可能会越过局部最小值导致无法收敛。
解决上述问题的办法:
1.可以画出J(θ)的函数图像看看是否要变化 α

!!!注意:
1.在梯度下降法中,当我们接近局部最低点时,梯度下降法会自动采取更小的幅度,这是因为当我们接近局部最低点时,很显然在局部最低时导数等于零,所以当我们接近局部最低时,导数值会自动变得越来越小,所以梯度下降将自动采取较小的幅度,这就是梯度下降的做法。所以实际上没有必要再另外减小a
2.当参数已经在一个局部的最优处或局部最低点。结果是局部最优点的导数将等于零,此时(θ01,…,θn )将不再变化。
在这里插入图片描述

批量梯度下降

非正则化算法: R p e a t { θ j = θ j − α m ∑ i = 1 m ( h θ ( x i ) − y ( i ) ) x j ( i ) j = 0 , 1 , . . . , n } \begin{array}{l} Rpeat\{ \\ {\theta _j} = {\theta _j} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{\rm{i}}}) - {y^{(i)}}){x_j}^{(i)}} \\ j = 0,1,...,n \\ \} \end{array} Rpeat{θj=θjmαi=1m(hθ(xi)y(i))xj(i)j=0,1,...,n}
注意:
1.批量梯度下降算法顾名思义,就是指在梯度下降中更新每一个参数θj中,都要用到所有的训练样本
2.x0=1

正则化算法:
R p e a t { θ 0 = θ 0 − α m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) θ j = ( 1 − α λ m ) θ j − α m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) j = 0 , 1 , . . . , n } \begin{array}{l} Rpeat\{ \\ {\theta _0} = {\theta _0} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}}){x_0}^{(i)}} \\ {\theta _j} = (1 - \frac{{\alpha \lambda }}{m}){\theta _j} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}}){x_j}^{(i)}}\\ j = 0,1,...,n \\ \} \end{array}\\ Rpeat{θ0=θ0mαi=1m(hθ(x(i))y(i))x0(i)θj=(1mαλ)θjmαi=1m(hθ(x(i))y(i))xj(i)j=0,1,...,n}

特征缩放

如果每个输入的n+1个特征中,有些特征差距很大,此时应该考虑特征缩放,特征缩放可以使得梯度下降时收敛更快
方法: x n = x n − μ n s n μ n : 均 值 , s n : 标 准 差 ( x . m a x − x . m i n ) \begin{array}{l} {x_n} = \frac{{{x_n} - {\mu _n}}}{{{s_n}}}\\ {\mu _n}:均值,{s_n}:标准差(x.max - x.min) \end{array} xn=snxnμnμn:,sn:x.maxx.min
注意:X是n+1维度的特征向量

代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#导入.txt文件的一种方式
path =  'ex1data2.txt'
data2 = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
data2.head()

#特征缩放
data2 = (data2 - data2.mean()) / data2.std()
data2.head()

#数据的预处理
# add ones column
data2.insert(0, 'Ones', 1)
# set X (training data) and y (target variable)
cols = data2.shape[1]
X2 = data2.iloc[:,0:cols-1]
y2 = data2.iloc[:,cols-1:cols]
# convert to matrices and initialize theta
X2 = np.matrix(X2.values)
y2 = np.matrix(y2.values)
theta2 = np.matrix(np.array([0,0,0]))#此处因为特征有两个变量和一个x0==1
# perform linear regression on the data set
g2, cost2 = gradientDescent(X2, y2, theta2, alpha, iters)
# get the cost (error) of the model
computeCost(X2, y2, g2)

#代价函数
def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)
    return np.sum(inner) / (2 * len(X))

#批量梯度下降
def gradientDescent(X, y, theta, alpha, iters):
	#创建一个改变theta的临时变量temp
    temp = np.matrix(np.zeros(theta.shape))
    parameters = int(theta.ravel().shape[1])
    cost = np.zeros(iters)
    for i in range(iters):
        error = (X * theta.T) - y
        for j in range(parameters):
            term = np.multiply(error, X[:,j])#即数组对应位置元素相乘
            temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
        theta = temp
        cost[i] = computeCost(X, y, theta)
    return theta, cost

#画模拟图
x = np.linspace(data.Population.min(), data.Population.max(), 100)
f = g[0, 0] + (g[0, 1] * x)
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

#画代价函数图
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

逻辑回归(分类算法)

性质

1.我们要预测的数据有0,1两种预测结果,若使用线性回归,会导致hθ(x)的值<0 or >1,因此此时要变化hθ(x),使得它的输出值永远在0-1之间
2.hθ(x)的作用是,对于给定的输入变量,根据选择的参数计算输出变量=1的可能性,即hθ (x)=P(y=1|x;θ) ,例如,如果对于给定的x,通过已经确定的参数计算得出hθ (x)=0.7,则表示有70%的几率y为正向类,相应地y为负向类的几率为1-0.7=0.3。
3.在这里插入图片描述
当hθ (x)>=0.5时,预测 y=1。
当hθ (x)<0.5时,预测 y=0 。
根据上面绘制出的 S 形函数图像,我们知道当
z=0 时 g(z)=0.5
z>0 时 g(z)>0.5
z<0 时 g(z)<0.5
又 z=θT x ,即:
θ^T x>=0 时,预测 y=1
θ^T x<0 时,预测 y=0
4.运用特征缩放可以使得模型收敛的更快

代价函数

假设函数: h θ ( x ) = 1 1 + e − θ T x {h_\theta }(x) = \frac{1}{{1 + {e^{ - {\theta ^T}x}}}} hθ(x)=1+eθTx1
注意:
将该假设函数带入均方误差代价函数,即 J ( θ 0 , θ 1 , . . . , θ n ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J({{\theta }_{\text{0}}},{{\theta }_{1}},...,{{\theta }_{n}})=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{({{h}_{\theta }}({{x}^{(i)}})-{{y}^{(i)}})}^{2}}} J(θ0,θ1,...,θn)=2m1i=1m(hθ(x(i))y(i))2时,得到的将是一个非凸函数,此时会有许多局部最小值,这将影响梯度下降算法寻找全局最小值!
在这里插入图片描述
定义新的代价函数:
J ( θ ) = 1 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) , y ( i ) ) J(\theta ) = \frac{1}{m}\sum\limits_{i = 1}^m {{\mathop{\rm Cos}\nolimits} t({h_\theta }({x^{(i)}}),{y^{(i)}})} J(θ)=m1i=1mCost(hθ(x(i)),y(i))
目标
当实际的 y=1 且hθ (x)也为 1 时误差为 0,当 y=1 但hθ (x)不为1时误差随着hθ (x)变小而变大;当实际的 y=0 且hθ (x)也为 0 时代价为 0,当y=0 但hθ (x)不为 0时误差随着 hθ (x)的变大而变大,后面运用梯度下降时,代价函数的误差越大,那么参数的调整幅度也越大。
函数设计
C o s t ( h θ ( x ) , y ) = { − log ⁡ ( h θ ( x ) ) , y = 1 − log ⁡ ( 1 − h θ ( x ) ) , y = 0 {\mathop{\rm Cos}\nolimits} t({h_\theta }(x),y) = \left\{ \begin{array}{l} - \log ({h_\theta }(x)),y = 1\\- \log (1 - {h_\theta }(x)),y = 0\end{array} \right. Cost(hθ(x),y)={log(hθ(x)),y=1log(1hθ(x)),y=0
hθ (x)与 Cost(hθ (x),y)之间的关系如下图所示:
在这里插入图片描述
合并
C o s t ( h θ ( x ) , y ) = − y log ⁡ ( h θ ( x ) ) − ( 1 − y ) log ⁡ ( 1 − h θ ( x ) ) {\mathop{\rm Cos}\nolimits} t({h_\theta }(x),y) = - {\rm{y}}\log ({h_\theta }(x)) - (1 - y)\log (1 - {h_\theta }(x)) Cost(hθ(x),y)=ylog(hθ(x))(1y)log(1hθ(x))
整理:
J ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) log ⁡ ( h θ ( x ( i ) ) + ( 1 − y ( i ) ) log ⁡ ( 1 − h θ ( x ( i ) ) ] J(\theta ) = - \frac{1}{m}\sum\limits_{i = 1}^m {\left[ {{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})} \right]} J(θ)=m1i=1m[y(i)log(hθ(x(i))+(1y(i))log(1hθ(x(i))]
正则化代价函数
J ( θ ) = − 1 m ∑ i = 1 m [ y ( i ) log ⁡ ( h θ ( x ( i ) ) + ( 1 − y ( i ) ) log ⁡ ( 1 − h θ ( x ( i ) ) ] + λ 2 m ∑ j = 1 n θ j 2 J(\theta ) = - \frac{1}{m}\sum\limits_{i = 1}^m {\left[ {{y^{(i)}}\log ({h_\theta }({x^{(i)}}) + (1 - {y^{(i)}})\log (1 - {h_\theta }({x^{(i)}})} \right]} + \frac{\lambda }{{2m}}\sum\limits_{j = 1}^n {{\theta _j}^2} J(θ)=m1i=1m[y(i)log(hθ(x(i))+(1y(i))log(1hθ(x(i))]+2mλj=1nθj2
注意:θ0不参与正则化

梯度下降

1.要注意和线性回归的区别:
h θ ( x ) = 1 1 + e − θ T x {h_\theta }(x) = \frac{1}{{1 + {e^{ - {\theta ^T}x}}}} hθ(x)=1+eθTx1
2.更新参数时,尽量使用向量化形式而非循环(多核处理器)
非正则化代价函数的梯度下降:
Want minθJ(θ):
R p e a t { θ j = θ j − α m ∑ i = 1 m ( h θ ( x i ) − y ( i ) ) x j ( i ) j = 0 , 1 , . . . , n } \begin{array}{l} Rpeat\{ \\ {\theta _j} = {\theta _j} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{\rm{i}}}) - {y^{(i)}}){x_j}^{(i)}} \\ j = 0,1,...,n \\ \} \end{array} Rpeat{θj=θjmαi=1m(hθ(xi)y(i))xj(i)j=0,1,...,n}
正则化代价函数的梯度下降:
R p e a t { θ 0 = θ 0 − α m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) θ j = ( 1 − α λ m ) θ j − α m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) j = 0 , 1 , . . . , n } \begin{array}{l} Rpeat\{ \\ {\theta _0} = {\theta _0} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}}){x_0}^{(i)}} \\ {\theta _j} = (1 - \frac{{\alpha \lambda }}{m}){\theta _j} - \frac{\alpha }{m}\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}}){x_j}^{(i)}}\\ j = 0,1,...,n \\ \} \end{array}\\ Rpeat{θ0=θ0mαi=1m(hθ(x(i))y(i))x0(i)θj=(1mαλ)θjmαi=1m(hθ(x(i))y(i))xj(i)j=0,1,...,n}

多分类问题(1对多)

模型: hθ(i) (x)=p(y=i|x;θ),i=(1,2,3…k)
解释:共有k个要分类的样本,现在将第i类分为正向类,其余都分为负向类,该模型便表示,再某特征和参数下,为第i类的概率。
分类算法:
将k个模型机依次带入要分类的特征,选择 max ⁡ i h θ ( i ) ( x ) \mathop {\max }\limits_i {h_\theta }^{(i)}(x) imaxhθ(i)(x),这一i类即为要选择类别

代码

#sigmoid 函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

#没有好的直线决策边界时,创建一个新的多项式特征
#此处原数据有 两个特征 test1,test2,一个结果
#创建的特征:x1+x1x2+x1^2+x1^2x2+x1x2^2+x1^3+..+x1^4
degree = 5
x1 = data2['Test 1']
x2 = data2['Test 2']
data2.insert(3, 'Ones', 1)
for i in range(1, degree):
    for j in range(0, i):
        data2['F' + str(i) + str(j)] = np.power(x1, i-j) * np.power(x2, j)
data2.drop('Test 1', axis=1, inplace=True)
data2.drop('Test 2', axis=1, inplace=True)
data2.head()

#正则化代价函数
def cost(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))
    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))
    reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))
    return np.sum(first - second) / len(X) + reg

#正则化梯度下降(此处只写出那个偏导项)
def gradientReg(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    parameters = int(theta.ravel().shape[1])
    grad = np.zeros(parameters)
    error = sigmoid(X * theta.T) - y
    for i in range(parameters):
        term = np.multiply(error, X[:,i])
        if (i == 0):
            grad[i] = np.sum(term) / len(X)
        else:
            grad[i] = (np.sum(term) / len(X)) + ((learningRate / len(X)) * theta[:,i])
    return grad

#初始化
 set X and y (remember from above that we moved the label to column 0)
cols = data2.shape[1]
X2 = data2.iloc[:,1:cols]
y2 = data2.iloc[:,0:1]
# convert to numpy arrays and initalize the parameter array theta
X2 = np.array(X2.values)
y2 = np.array(y2.values)
theta2 = np.zeros(11)

#获得代价函数取得最小值的参数,x0是要变化的值,args是输入常量
#正则化参数learningRate可以调节
import scipy.optimize as opt
result2 = opt.fmin_tnc(func=costReg, x0=theta2, fprime=gradientReg, args=(X2, y2, learningRate))

#结果预测
def predict(theta, X):
    probability = sigmoid(X * theta.T)
    return [1 if x >= 0.5 else 0 for x in probability]

theta_min = np.matrix(result2[0])
predictions = predict(theta_min, X2)
correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y2)]
accuracy = (sum(correct)) % len(correct))
print ('accuracy = {0}%'.format(accuracy))

神经网络(适用于多对多)

神经网络与逻辑回归

逻辑回归其实等于一个具有一个输出单元的神经网络,如图:
在这里插入图片描述
如果添加了隐藏层,那么便相当于把最后一个隐藏层看作是逻辑回归的输入,前面的做法是为了得到更高级的特征(重新选择输入),该方法要远好于添加多项式。
在这里插入图片描述

算法流程

注意:
1.如果有多个隐藏层,那么确保每个隐藏层的神经元个数相同,并且隐藏层算出来后要加一个偏执单元。
2.对于每一层的权重,应该随机初始化为 − ε ≤ θ i j ( l ) ≤ ε {\rm{ - }}\varepsilon \le {\theta _{{\rm{ij}}}}^{(l)} \le \varepsilon εθij(l)ε,绝对不能初始化都为0,或则同一个数,因为这样会导致所有层的激活单元都是相同的值
3.θ ij(l) 代表l层的第j个单元连接l+1层第i个单元的权值
4.θ (l) 代表第l层到l+1层的权值矩阵,尺寸:l+1层的激活单元数 X (l层激活单元数+1)
5.aj(l) 代表第l层的第j个激活单元
6.下图有4个输出,因此对于不同的输出,hθ(x)可以表示为在这里插入图片描述
即热独编码

正则化代价函数

J ( Θ ) = − 1 m [ ∑ i = 1 m ∑ k = 1 k y k ( i ) log ⁡ ( h Θ ( x ( i ) ) ) k + ( 1 − y k ( i ) ) log ⁡ ( 1 − ( h Θ ( x ( i ) ) ) k ) ] + λ 2 m ∑ l = 1 L − 1 ∑ i = 1 s l ∑ j = 1 s l + 1 ( Θ j i ( l ) ) 2 \begin{array}{l}J(\Theta ) = - \frac{1}{m}\left[ {\sum\limits_{i = 1}^m {\sum\limits_{k = 1}^k {{y_k}^{(i)}} } \log {{\left( {{h_\Theta }\left( {{x^{(i)}}} \right)} \right)}_k} + \left( {1 - y_k^{(i)}} \right)\log \left( {1 - {{\left( {{h_\Theta }\left( {{x^{(i)}}} \right)} \right)}_k}} \right)} \right]\\+ \frac{\lambda }{{2m}}\sum\limits_{l = 1}^{L - 1} {\sum\limits_{i = 1}^{{s_l}} {\sum\limits_{j = 1}^{{s_l} + 1} {{{\left( {\Theta _{ji}^{(l)}} \right)}^2}} } } \end{array} J(Θ)=m1[i=1mk=1kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+2mλl=1L1i=1slj=1sl+1(Θji(l))2
注意:
1.sl:代表第l层的激活单元的数量
2.正则化的那一项只是排除了每一层θ_0后,每一层的θ 矩阵的和。

前向传播

设该神经网络是添加了偏执的完整神经网络
在这里插入图片描述
解释:
a ( 2 ) = ( a 1 ( 2 ) a 2 ( 2 ) a 3 ( 2 ) a 4 ( 2 ) ) = g ( ( θ 10 ( 1 ) θ 11 ( 1 ) θ 12 ( 1 ) θ 20 ( 1 ) θ 21 ( 1 ) θ 22 ( 1 ) θ 30 ( 1 ) θ 31 ( 1 ) θ 32 ( 1 ) θ 40 ( 1 ) θ 41 ( 1 ) θ 42 ( 1 ) ) × ( a 0 ( 1 ) a 1 ( 1 ) a 2 ( 1 ) ) ) {{a}^{(2)}}=\left( \begin{matrix} {{a}_{1}}^{(2)} \\ {{a}_{2}}^{(2)} \\ {{a}_{3}}^{(2)} \\ {{a}_{4}}^{(2)} \\ \end{matrix} \right)=g\left( \left( \begin{matrix} {{\theta }_{10}}^{(1)} & {{\theta }_{11}}^{(1)} & {{\theta }_{12}}^{(1)} \\ {{\theta }_{20}}^{(1)} & {{\theta }_{21}}^{(1)} & {{\theta }_{22}}^{(1)} \\ {{\theta }_{30}}^{(1)} & {{\theta }_{31}}^{(1)} & {{\theta }_{32}}^{(1)} \\ {{\theta }_{40}}^{(1)} & {{\theta }_{41}}^{(1)} & {{\theta }_{42}}^{(1)} \\ \end{matrix} \right)\times \left( \begin{matrix} {{a}_{0}}^{(1)} \\ {{a}_{1}}^{(1)} \\ {{a}_{2}}^{(1)} \\ \end{matrix} \right) \right) a(2)=a1(2)a2(2)a3(2)a4(2)=gθ10(1)θ20(1)θ30(1)θ40(1)θ11(1)θ21(1)θ31(1)θ41(1)θ12(1)θ22(1)θ32(1)θ42(1)×a0(1)a1(1)a2(1)

a ( 3 ) = ( a 1 ( 3 ) a 2 ( 3 ) a 3 ( 3 ) a 4 ( 3 ) ) = g ( ( θ 10 ( 2 ) θ 11 ( 2 ) θ 12 ( 2 ) θ 13 ( 2 ) θ 14 ( 2 ) θ 20 ( 2 ) θ 21 ( 2 ) θ 22 ( 2 ) θ 23 ( 2 ) θ 24 ( 2 ) θ 30 ( 2 ) θ 31 ( 2 ) θ 32 ( 2 ) θ 33 ( 2 ) θ 34 ( 2 ) θ 40 ( 2 ) θ 41 ( 2 ) θ 42 ( 2 ) θ 43 ( 2 ) θ 44 ( 2 ) ) × ( a 0 ( 2 ) a 1 ( 2 ) a 2 ( 2 ) a 3 ( 2 ) a 4 ( 2 ) ) ) {{a}^{(3)}}=\left( \begin{matrix} {{a}_{1}}^{(3)} \\ {{a}_{2}}^{(3)} \\ {{a}_{3}}^{(3)} \\ {{a}_{4}}^{(3)} \\ \end{matrix} \right)=g\left( \left( \begin{matrix} {{\theta }_{10}}^{(2)} & {{\theta }_{11}}^{(2)} & {{\theta }_{12}}^{(2)} & {{\theta }_{13}}^{(2)} & {{\theta }_{14}}^{(2)} \\ {{\theta }_{20}}^{(2)} & {{\theta }_{21}}^{(2)} & {{\theta }_{22}}^{(2)} & {{\theta }_{23}}^{(2)} & {{\theta }_{24}}^{(2)} \\ {{\theta }_{30}}^{(2)} & {{\theta }_{31}}^{(2)} & {{\theta }_{32}}^{(2)} & {{\theta }_{33}}^{(2)} & {{\theta }_{34}}^{(2)} \\ {{\theta }_{40}}^{(2)} & {{\theta }_{41}}^{(2)} & {{\theta }_{42}}^{(2)} & {{\theta }_{43}}^{(2)} & {{\theta }_{44}}^{(2)} \\ \end{matrix} \right)\times \left( \begin{matrix} {{a}_{0}}^{(2)} \\ {{a}_{1}}^{(2)} \\ {{a}_{2}}^{(2)} \\ {{a}_{3}}^{(2)} \\ {{a}_{4}}^{(2)} \\ \end{matrix} \right) \right) a(3)=a1(3)a2(3)a3(3)a4(3)=gθ10(2)θ20(2)θ30(2)θ40(2)θ11(2)θ21(2)θ31(2)θ41(2)θ12(2)θ22(2)θ32(2)θ42(2)θ13(2)θ23(2)θ33(2)θ43(2)θ14(2)θ24(2)θ34(2)θ44(2)×a0(2)a1(2)a2(2)a3(2)a4(2)
h θ ( x ) = a ( 4 ) = ( a 1 ( 4 ) a 2 ( 4 ) a 3 ( 4 ) a 4 ( 4 ) ) = g ( ( θ 10 ( 3 ) θ 11 ( 3 ) θ 12 ( 3 ) θ 13 ( 3 ) θ 14 ( 3 ) θ 20 ( 3 ) θ 21 ( 3 ) θ 22 ( 3 ) θ 23 ( 3 ) θ 24 ( 3 ) θ 30 ( 3 ) θ 31 ( 3 ) θ 32 ( 3 ) θ 33 ( 3 ) θ 34 ( 3 ) θ 40 ( 3 ) θ 41 ( 3 ) θ 42 ( 3 ) θ 43 ( 3 ) θ 44 ( 3 ) ) × ( a 0 ( 3 ) a 1 ( 3 ) a 2 ( 3 ) a 3 ( 3 ) a 4 ( 3 ) ) ) {{h}_{\theta }}(x)={{a}^{(4)=}}\left( \begin{matrix} {{a}_{1}}^{(4)} \\ {{a}_{2}}^{(4)} \\ {{a}_{3}}^{(4)} \\ {{a}_{4}}^{(4)} \\ \end{matrix} \right)=g\left( \left( \begin{matrix} {{\theta }_{10}}^{(3)} & {{\theta }_{11}}^{(3)} & {{\theta }_{12}}^{(3)} & {{\theta }_{13}}^{(3)} & {{\theta }_{14}}^{(3)} \\ {{\theta }_{20}}^{(3)} & {{\theta }_{21}}^{(3)} & {{\theta }_{22}}^{(3)} & {{\theta }_{23}}^{(3)} & {{\theta }_{24}}^{(3)} \\ {{\theta }_{30}}^{(3)} & {{\theta }_{31}}^{(3)} & {{\theta }_{32}}^{(3)} & {{\theta }_{33}}^{(3)} & {{\theta }_{34}}^{(3)} \\ {{\theta }_{40}}^{(3)} & {{\theta }_{41}}^{(3)} & {{\theta }_{42}}^{(3)} & {{\theta }_{43}}^{(3)} & {{\theta }_{44}}^{(3)} \\ \end{matrix} \right)\times \left( \begin{matrix} {{a}_{0}}^{(3)} \\ {{a}_{1}}^{(3)} \\ {{a}_{2}}^{(3)} \\ {{a}_{3}}^{(3)} \\ {{a}_{4}}^{(3)} \\ \end{matrix} \right) \right) hθ(x)=a(4)=a1(4)a2(4)a3(4)a4(4)=gθ10(3)θ20(3)θ30(3)θ40(3)θ11(3)θ21(3)θ31(3)θ41(3)θ12(3)θ22(3)θ32(3)θ42(3)θ13(3)θ23(3)θ33(3)θ43(3)θ14(3)θ24(3)θ34(3)θ44(3)×a0(3)a1(3)a2(3)a3(3)a4(3)
注意:其中的a0都是0,而且这只是一个样本的输入,对于矩阵,应表示为z=θXT

反向传播

注意,是权值导致的误差
δ ( 4 ) = a ( 4 ) − y {{\delta }^{(4)}}={{a}^{(4)}}-y δ(4)=a(4)y
δ ( 3 ) = ( θ ( 3 ) ) T δ ( 4 ) ∗ g ′ ( z ( 3 ) ) {{\delta }^{(3)}}={{({{\theta }^{(3)}})}^{T}}{{\delta }^{(4)}}*{{g}^{'}}({{z}^{(3)}}) δ(3)=(θ(3))Tδ(4)g(z(3))
g ′ ( z ( 3 ) ) = a ( 3 ) ∗ ( 1 − a ( 3 ) ) , a ( 3 ) = g ( z ( 3 ) ) {{g}^{'}}({{z}^{(3)}})={{a}^{(3)}}*(1-{{a}^{(3)}}),{{a}^{(3)}}=g({{z}^{(3)}}) g(z(3))=a(3)(1a(3)),a(3)=g(z(3))
δ ( 2 ) = ( θ ( 2 ) ) T δ ( 3 ) ∗ g ′ ( z ( 2 ) ) {{\delta }^{(2)}}={{({{\theta }^{(2)}})}^{T}}{{\delta }^{(3)}}*{{g}^{'}}({{z}^{(2)}}) δ(2)=(θ(2))Tδ(3)g(z(2))
g ′ ( z ( 2 ) ) = a ( 2 ) ∗ ( 1 − a ( 2 ) ) , a ( 2 ) = g ( z ( 2 ) ) {{g}^{'}}({{z}^{(2)}})={{a}^{(2)}}*(1-{{a}^{(2)}}),{{a}^{(2)}}=g({{z}^{(2)}}) g(z(2))=a(2)(1a(2)),a(2)=g(z(2))
注意:没有δ (1) ,下述是整个训练集上的训练计划
在这里插入图片描述

正则化梯度下降(包含梯度校验)

{ D i j ( l ) = ∂ J ( θ ) ∂ θ i j ( l ) = J ( θ 10 ( 1 ) , . . . , θ i j ( l ) + ε , . . . θ s L s L − 1 ( L − 1 ) ) − J ( θ 10 ( 1 ) , . . . , θ i j ( l ) − ε , . . . θ s L s L − 1 ( L − 1 ) ) 2 ε D i j ( l ) = 1 m Δ i j ( l ) , j = 0 D i j ( l ) = 1 m Δ i j ( l ) + λ θ i j ( l ) , j ≠ 0 \left\{ \begin{array}{l} {D_{ij}}^{(l)} = \frac{{\partial J(\theta )}}{{\partial {\theta _{ij}}^{(l)}}} = \frac{{J({\theta _{10}}^{(1)},...,{\theta _{ij}}^{(l)} + \varepsilon ,...{\theta _{{s_L}{s_{L - 1}}}}^{(L - 1)}) - J({\theta _{10}}^{(1)},...,{\theta _{ij}}^{(l)} - \varepsilon ,...{\theta _{{s_L}{s_{L - 1}}}}^{(L - 1)})}}{{2\varepsilon }}\\ {D_{ij}}^{(l)} = \frac{1}{m}{\Delta _{ij}}^{(l)},j = 0\\ {D_{ij}}^{(l)} = \frac{1}{m}{\Delta _{ij}}^{(l)} + \lambda {\theta _{ij}}^{(l)},j \ne 0 \end{array} \right. Dij(l)=θij(l)J(θ)=2εJ(θ10(1),...,θij(l)+ε,...θsLsL1(L1))J(θ10(1),...,θij(l)ε,...θsLsL1(L1))Dij(l)=m1Δij(l),j=0Dij(l)=m1Δij(l)+λθij(l),j=0

多网络融合

下图的神经元(三个权重分别为-30,20,20)可以被视为作用同于逻辑与(AND):
在这里插入图片描述

下图的神经元(三个权重分别为-10,20,20)可以被视为作用等同于逻辑或(OR):
在这里插入图片描述

下图的神经元(两个权重分别为 10,-20)可以被视为作用等同于逻辑非(NOT):
在这里插入图片描述
(NOT x1 )AND(NOT x2 ):

在这里插入图片描述
XNOR=(x1 AND x2) OR((NOT x1 )AND(NOT x2 )):
在这里插入图片描述

代码

注意:所求神经网络模型:(400 + 1) -> (25 + 1) -> (10)
传播时矩阵的维度考虑清楚,内部不会有问题的

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
#导入.mat文件
data = loadmat('ex4data1.mat')

#热独编码编写方式
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse=False)
y_onehot = encoder.fit_transform(y)
y_onehot.shape
y_onehot

def expand_y(y):
#     """expand 5000*1 into 5000*10
#变成热独编码
#     where y=10 -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]: ndarray
#     """
    res = []
    for i in y:
        y_array = np.zeros(10)
        y_array[i - 1] = 1
        res.append(y_array)
    return np.array(res)
#前向传播
#theta1 :25x401 theta2: 10x26 a1:5000x401 a2:5000x25 h(a2)=5000x10
def sigmoid(z):
    return 1 / (1 + np.exp(-z))
def forward_propagate(X, theta1, theta2):
    m = X.shape[0]
    a1 = np.insert(X, 0, values=np.ones(m), axis=1)
    z2 = a1 * theta1.T
    a2 = np.insert(sigmoid(z2), 0, values=np.ones(m), axis=1)
    z3 = a2 * theta2.T
    h = sigmoid(z3)
    return a1, z2, a2, z3, h

#正则化代价函数
#params:一维参数矩阵,y:热独编码形式
def cost(params, input_size, hidden_size, num_labels, X, y, learning_rate):
    m = X.shape[0]
    X = np.matrix(X)
    y = np.matrix(y)
    # reshape the parameter array into parameter matrices for each layer
    theta1 = np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))
    theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))
    # run the feed-forward pass
    a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
    # compute the cost
    J = 0
    for i in range(m):
        first_term = np.multiply(-y[i,:], np.log(h[i,:]))
        second_term = np.multiply((1 - y[i,:]), np.log(1 - h[i,:]))
        J += np.sum(first_term - second_term)
    J = J / m
    # add the cost regularization term
    J += (float(learning_rate) / (2 * m)) * (np.sum(np.power(theta1[:,1:], 2)) + np.sum(np.power(theta2[:,1:], 2)))
    return J

#反向传播
#g'(z)
def sigmoid_gradient(z):
    return np.multiply(sigmoid(z), (1 - sigmoid(z)))
    
def backprop(params, input_size, hidden_size, num_labels, X, y, learning_rate):
    m = X.shape[0]
    X = np.matrix(X)
    y = np.matrix(y)
    # reshape the parameter array into parameter matrices for each layer
    theta1 = np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))
    theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))
    # run the feed-forward pass
    a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
    # initializations
    J = 0
    delta1 = np.zeros(theta1.shape)  # (25, 401),与theta尺寸相同
    delta2 = np.zeros(theta2.shape)  # (10, 26)
    # compute the cost
    for i in range(m):
        first_term = np.multiply(-y[i,:], np.log(h[i,:]))
        second_term = np.multiply((1 - y[i,:]), np.log(1 - h[i,:]))
        J += np.sum(first_term - second_term)
    J = J / m
    # add the cost regularization term
    J += (float(learning_rate) / (2 * m)) * (np.sum(np.power(theta1[:,1:], 2)) + np.sum(np.power(theta2[:,1:], 2)))
    # perform backpropagation
    for t in range(m):
        a1t = a1[t,:]  # (1, 401)
        z2t = z2[t,:]  # (1, 25)
        a2t = a2[t,:]  # (1, 26)
        ht = h[t,:]  # (1, 10)
        yt = y[t,:]  # (1, 10)
        
        d3t = ht - yt  # (1, 10)
        z2t = np.insert(z2t, 0, values=np.ones(1))  # (1, 26)
        d2t = np.multiply((theta2.T * d3t.T).T, sigmoid_gradient(z2t))  # (1, 26)
        
        delta1 = delta1 + (d2t[:,1:]).T * a1t
        delta2 = delta2 + d3t.T * a2t
        
    delta1 = delta1 / m
    delta2 = delta2 / m
    # add the gradient regularization term
    delta1[:,1:] = delta1[:,1:] + (theta1[:,1:] * learning_rate) / m
    delta2[:,1:] = delta2[:,1:] + (theta2[:,1:] * learning_rate) / m
    # unravel the gradient matrices into a single array
    grad = np.concatenate((np.ravel(delta1), np.ravel(delta2)))
    
    return J, grad
    
#参数初始化
# 初始化设置
input_size = 400
hidden_size = 25
num_labels = 10
learning_rate = 1
# 随机初始化完整网络参数大小的参数数组
params = (np.random.random(size=hidden_size * (input_size + 1) + num_labels * (hidden_size + 1)) - 0.5) * 0.25
m = X.shape[0]
X = np.matrix(X)
y = np.matrix(y)

#模型训练与预测
from scipy.optimize import minimize

# minimize the objective function
fmin = minimize(fun=backprop, x0=params, args=(input_size, hidden_size, num_labels, X, y_onehot, learning_rate), 
                method='TNC', jac=True, options={'maxiter': 250})
fmin

X = np.matrix(X)
theta1 = np.matrix(np.reshape(fmin.x[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))
theta2 = np.matrix(np.reshape(fmin.x[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))
a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
y_pred = np.array(np.argmax(h, axis=1) + 1)
y_pred

correct = [1 if a == b else 0 for (a, b) in zip(y_pred, y)]
accuracy = (sum(map(int, correct)) / float(len(correct)))
print ('accuracy = {0}%'.format(accuracy * 100))

支持向量机

优化目标

对于逻辑回归来说,
1.预测y1时,我们希望θT x远大于0时,hθ(x)约等于1
2.预测y
0时,我们希望θT x远小于0时,hθ(x)约等于0,
在这里插入图片描述
SVM的优化:
1.代价函数的优化(曲线变直线):
在这里插入图片描述
2.判断条件的优化:
因为逻辑回归只要>=0 or <0,SVM是以1和-1区分的
在这里插入图片描述

线性SVM(无核)代价函数

min ⁡ θ C ∑ i = 1 m [ y ( i ) c o s t 1 ( θ T x ( i ) ) + ( 1 − y ( i ) ) c o s t 0 ( θ T x ( i ) ) ] + 1 2 ∑ j = 1 m θ j 2 \mathop {\min }\limits_\theta C\sum\limits_{i = 1}^m {\left[ {{y^{(i)}}cos{t_1}({\theta ^T}{x^{(i)}}) + (1 - {y^{(i)}})cos{t_0}({\theta ^T}{x^{(i)}})} \right] + \frac{1}{2}} \sum\limits_{j = 1}^m {{\theta _j}^2} θminCi=1m[y(i)cost1(θTx(i))+(1y(i))cost0(θTx(i))]+21j=1mθj2
CA+B(C等价于1/lamda)
h θ ( x ) = { 1 , i f θ T x ≥ 1 0 , i f θ T x ≤ − 1 {h_\theta }(x) = \left\{ \begin{array}{l} 1,{\rm{ }}if{\theta ^T}x \ge 1\\ 0,{\rm{ }}if{\theta ^T}x \le - 1 \end{array} \right. hθ(x)={1,ifθTx10,ifθTx1

解释SVM为大边界分类器

在这里插入图片描述
在这里插入图片描述

向量u,v的内积为: vTu=uT v=p⬝∥u∥=u1×v1+u2×v2
注意:p是有正负的
简化版SVM决策假设
目标:让θ变小
在这里插入图片描述
分类过程:
注意:1.此处假设θ0=0,因此可以一直过原点
2.边界为θTX=0,所有决策边界(那些使θTX=0得点)与θ是垂直的
在这里插入图片描述
P(i)⋅∥θ∥>=1 or P(i)⋅∥θ∥<=-1 ,分类点如果在θ向量上得投影越大(P(i)越大),那么∥θ∥越小,目标越小。观察左右两个绿色得边界,发现右图会是SVM选择得那一类

高斯核

曲线边界拟合的办法

在这里插入图片描述
1.为了获得上图所示的判定边界,我们的模型可能是θ01 x12 x23 x1 x2+ θ4 x125x22+⋯的形式。
我们可以用一系列的新的特征f来替换模型中的每一项。例如令: f1=x1,f2=x2,f3=x1 x2,f4=x12,f5=x22
得到hθ (x)=θ1f12 f2+…+θn fn

在这里插入图片描述

给定一个训练实例x(最后验证时带入的),我们利用x的各个特征与我们预先选定的地标(landmarks)l(1),l(2),l(3)的近似程度来选取新的特征f1,f2,f3。(一个思想:有多少个训练集,就用多少个f)

f ( i ) = s i m a l i r i t y ( x , l ( i ) ) = e − ∥ x − l ( i ) ∥ 2 2 σ 2 {f_{(i)}} = simalirity(x,{l^{(i)}}) = {e^{ - \frac{{{{\left\| {x - {l^{(i)}}} \right\|}^2}}}{{2{\sigma ^2}}}}} f(i)=simalirity(x,l(i))=e2σ2xl(i)2
∥ x − l ( i ) ∥ 2 = ∑ j = 1 n ( x j − l j ( i ) ) 2 {\left\| {x - {l^{(i)}}} \right\|^2} = \sum\limits_{j = 1}^n {{{({x_j} - {l_j}^{(i)})}^2}} xl(i)2=j=1n(xjlj(i))2

这些地标的作用是什么?如果一个训练实例x与地标L之间的距离近似于0,则新特征 f近似于e(-0)=1,如果训练实例x与地标L之间距离较远,则f近似于e(-(一个较大的数))=0。
解释:
在上图中,当实例处于洋红色的点位置处,因为其离l(1)更近,但是离l(2)和l(3)较远,因此f1接近1,而f2,f3接近0。因此hθ(x)=θ01 f12 f21 f3>0,因此预测y=1。同理可以求出,对于离l^((2))较近的绿色点,也预测y=1,但是对于蓝绿色的点,因为其离三个地标都较远,预测y=0。

具有高斯核的SVM

如何选择地标:
如果训练集中有m个实例,则我们选取m个地标,并且令:l(1)=x(1),l(2)=x(2),…,l(m)=x(m)
θ与f(i) 维度相同
以上介绍了只有一个测试输入的时候,现在介绍有多个输入时
在这里插入图片描述
在这里插入图片描述
给定x,计算新特征f,当θT f>=0 时,预测 y=1,否则反之,不用在考虑1,-1
min ⁡ θ C ∑ i = 1 m [ y ( i ) c o s t 1 ( θ T f ( i ) ) + ( 1 − y ( i ) ) c o s t 0 ( θ T f ( i ) ) ] + 1 2 ∑ j = 1 m θ j 2 \mathop {\min }\limits_\theta C\sum\limits_{i = 1}^m {\left[ {{y^{(i)}}cos{t_1}({\theta ^T}{f^{(i)}}) + (1 - {y^{(i)}})cos{t_0}({\theta ^T}{f^{(i)}})} \right] + \frac{1}{2}} \sum\limits_{j = 1}^m {{\theta _j}^2} θminCi=1m[y(i)cost1(θTf(i))+(1y(i))cost0(θTf(i))]+21j=1mθj2
计算时 ∑ j = 1 m θ j 2 = θ T θ \sum\limits_{j = 1}^m {{\theta _j}^2} = {\theta ^T}\theta j=1mθj2=θTθ,我们用θT Mθ代替θ^T θ,其中M是根据我们选择的核函数而不同的一个矩阵。这样做的原因是为了简化计算

SVM与正则化

下面是支持向量机的两个参数C和σ的影响:
C=1/λ
C 较大时,相当于λ较小,可能会导致过拟合,高方差;
C 较小时,相当于λ较大,可能会导致低拟合,高偏差;
σ较大时,可能会导致低方差,高偏差;
σ较小时,可能会导致低偏差,高方差。

带不带核的使用准则

n为特征数,m为训练样本数。
(1)如果相较于m而言,n要大许多,即训练集数据量不够支持我们训练一个复杂的非线性模型,我们选用逻辑回归模型或者不带核函数的支持向量机。

(2)如果n较小,而且m大小中等,例如n在 1-1000 之间,而m在10-10000之间,使用高斯核函数的支持向量机。(10倍)

(3)如果n较小,而m较大,例如n在1-1000之间,而m大于50000,则使用支持向量机会非常慢,解决方案是创造、增加更多的特征,然后使用逻辑回归或不带核函数的支持向量机。(50倍)

值得一提的是,神经网络在以上三种情况下都可能会有较好的表现,但是训练神经网络可能非常慢,选择支持向量机的原因主要在于它的代价函数是凸函数,不存在局部最小值

代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat

#数据处理
data = pd.DataFrame(raw_data['X'], columns=['X1', 'X2'])
data['y'] = raw_data['y']
positive = data[data['y'].isin([1])]
negative = data[data['y'].isin([0])]
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(positive['X1'], positive['X2'], s=50, marker='x', label='Positive')
ax.scatter(negative['X1'], negative['X2'], s=50, marker='o', label='Negative')
ax.legend()
plt.show()

#线性SVM
from sklearn import svm
svc = svm.LinearSVC(C=1, loss='hinge', max_iter=1000)
svc.fit(data[['X1', 'X2']], data['y'])
svc.score(data[['X1', 'X2']], data['y'])
#该函数指的是每一个点到决策边界的距离
data['SVM 1 Confidence'] = svc.decision_function(data[['X1', 'X2']])
fig, ax = plt.subplots(figsize=(12,8))
#c是颜色的意思,值越小,颜色越浅
ax.scatter(data['X1'], data['X2'], s=50, c=data['SVM 1 Confidence'], cmap='seismic')
ax.set_title('SVM (C=1) Decision Confidence')
plt.show()

#高斯核函数
def gaussian_kernel(x1, x2, sigma):
    return np.exp(-(np.sum((x1 - x2) ** 2) / (2 * (sigma ** 2))))

#带核的SVM
#gamma 是核的参数
svc = svm.SVC(C=100, gamma=10, probability=True)
svc.fit(data[['X1', 'X2']], data['y'])
svc.score(data[['X1', 'X2']], data['y'])
#该函数指某一个点是某一类的概率,此处代表某一个点是第一个类的概率,每一行的加和为1
data['Probability'] = svc.predict_proba(data[['X1', 'X2']])[:,0]
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(data['X1'], data['X2'], s=30, c=data['Probability'], cmap='Reds')
plt.show()

模型优化与判断

拟合

欠拟合,正确拟合,过拟合:

在这里插入图片描述
在这里插入图片描述
就以多项式理解,x 的次数越高,拟合的越好,但相应的预测的能力就可能变差(泛化能力变差

过拟合解决方式:
1.丢弃一些不能帮助我们正确预测的特征。可以是手工选择保留哪些特征,或者使用一些模型选择的算法来帮忙(例如PCA)
2.正则化。 保留所有的特征,但是减少参数的大小(magnitude)

正则化解决过拟合问题

思想:
对参数θ0,…,θn设置一定的惩罚度,我们可以将惩罚机制放入代价函数,再使用梯度下降最小化cost
正则化代价函数
J ( θ ) = 1 2 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) , y ( i ) ) + λ 2 m ∑ j = 1 n θ j 2 J(\theta ) = \frac{1}{{2m}}\sum\limits_{i = 1}^m {{\mathop{\rm Cos}\nolimits} t({h_\theta }({x^{(i)}}),{y^{(i)}})} + \frac{\lambda }{{2m}}\sum\limits_{j = 1}^n {{\theta _j}^2} J(θ)=2m1i=1mCost(hθ(x(i)),y(i))+2mλj=1nθj2
注意:
1.j从1开始。
2.如果选择的正则化参数λ过大,则会把所有的参数都最小化了,导致模型变成 hθ (x)=θ0,极限情况是一条直线,造成欠拟合

选择一个模型

评估数据选择

使用60%的数据作为训练集,使用 20%的数据作为交叉验证集,使用20%的数据作为测试集
J t r a i n ( x ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 {J_{train}}(x) = \frac{1}{{2m}}{\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}})} ^2} Jtrain(x)=2m1i=1m(hθ(x(i))y(i))2
J c v ( x ) = 1 2 m c v ∑ i = 1 m ( h θ ( x c v ( i ) ) − y c v ( i ) ) 2 {J_{cv}}(x) = \frac{1}{{2{m_{cv}}}}{\sum\limits_{i = 1}^m {({h_\theta }({x_{cv}}^{(i)}) - {y_{cv}}^{(i)})} ^2} Jcv(x)=2mcv1i=1m(hθ(xcv(i))ycv(i))2

评估多个假设

在这里插入图片描述
模型选择的方法为:

  1. 使用训练集训练出10个模型
  2. 用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)
  3. 选取代价函数值最小的模型
  4. 用步骤3中选出的模型对测试集计算得出推广误差(代价函数的值)
评估正则化参数

注意:我们选择一系列的想要测试的 λ 值,通常是 0-10之间的呈现2倍关系的值
在这里插入图片描述
选择λ的方法为:
1.使用训练集训练出12个不同程度正则化的模型
2.用12个模型分别对交叉验证集计算的出交叉验证误差
3.选择得出交叉验证误差最小的模型
4.运用步骤3中选出模型对测试集计算得出推广误差

偏差和方差

偏差:欠拟合
方差:过拟合

偏差方差与多项式特征之间的关系

在这里插入图片描述

偏差方差与正则化参数之间的关系

在这里插入图片描述

高偏差与高方差的解决方式
  1. 获得更多的训练实例——解决高方差
  2. 尝试减少特征的数量——解决高方差
  3. 尝试获得更多的特征——解决高偏差
  4. 尝试增加多项式特征——解决高偏差
  5. 尝试减少正则化程度λ——解决高偏差
  6. 尝试增加正则化程度λ——解决高方差
神经网络的偏差与方差

使用较小的神经网络,类似于参数较少的情况,容易导致高偏差和欠拟合,但计算代价较小使用较大的神经网络,类似于参数较多的情况,容易导致高方差和过拟合,虽然计算代价比较大,但是可以通过正则化手段来调整而更加适应数据。
通常选择较大的神经网络并采用正则化处理会比采用较小的神经网络效果要好。

学习曲线

学习曲线:将训练集误差和交叉验证集误差(代价函数)作为训练集实例数量(m)的函数绘制的图表。
注意:绘制时一定是随着训练集m的增大,先更新参数,再计算训练集和测试集误差

高偏差情况

在这里插入图片描述
无论训练集有多么大误差都不会有太大改观,也就是说在高偏差/欠拟合的情况下,增加数据到训练集不一定能有帮助。

高方差的情况:

在这里插入图片描述
假设我们使用一个非常高次的多项式模型,并且正则化非常小(过拟合征兆),可以看出,当交叉验证集误差远大于训练集误差时,往训练集增加更多数据可以提高模型的效果。也就是说在高方差/过拟合的情况下,增加更多数据到训练集可能可以提高算法效果。

类偏斜

偏斜情况表现为我们的训练集中有非常多的同一种类的实例,只有很少或没有其他类的实例。

查准率,查全率,F1

混淆矩阵 预测值
Positive Negtive
实际值 Positive TP FN
Negtive FP TN
查准率=TP/(TP+FP)
查全率=TP/(TP+FN)
F1 Score: 2 PR/(P+R)
二者都是越高越好
在这里插入图片描述
如果我们希望只在非常确信的情况下预测为真(肿瘤为恶性),即我们希望更高的查准率,我们可以使用比0.5更大的阀值,如0.7,0.9。这样做我们会减少错误预测病人为恶性肿瘤的情况,同时却会增加未能成功预测肿瘤为恶性的情况。

如果我们希望提高查全率,尽可能地让所有有可能是恶性肿瘤的病人都得到进一步地检查、诊断,我们可以使用比0.5更小的阀值,如0.3。
那么如何选择呢?
我们选择可以使得F1值最大的数来作为阈值

构建学习算法

  1. 从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试这个算法
  2. 绘制学习曲线,决定是增加更多数据,或者添加更多特征,还是其他选择
  3. 进行误差分析:人工检查交叉验证集中我们算法中产生预测误差的实例,看看这些实例是否有某种系统化的趋势

代码

import numpy as np
import scipy.io as sio
import scipy.optimize as opt
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#对于pandas的画图
df = pd.DataFrame({'water_level':X, 'flow':y})
sns.lmplot('water_level', 'flow', data=df, fit_reg=False, size=7)
plt.show()

#特征工程
def normalize_feature(df):
    """Applies function along input axis(default 0) of DataFrame."""
    return df.apply(lambda column: (column - column.mean()) / column.std())

#创建多项式特征
def poly_features(x, power, as_ndarray=False):
    data = {'f{}'.format(i): np.power(x, i) for i in range(1, power + 1)}
    df = pd.DataFrame(data)
    return df.as_matrix() if as_ndarray else df

def prepare_poly_data(*args, power):
    """
    args: keep feeding in X, Xval, or Xtest
        will return in the same order
    """
    def prepare(x):
        # expand feature
        df = poly_features(x, power=power)
        # normalization
        ndarr = normalize_feature(df).as_matrix()
        # add intercept term
        return np.insert(ndarr, 0, np.ones(ndarr.shape[0]), axis=1)
    return [prepare(x) for x in args]
#代价函数
def cost(theta, X, y):
    """
    X: R(m*n), m records, n features
    y: R(m)
    theta : R(n), linear regression parameters
    """
    m = X.shape[0]
    inner = X @ theta - y  # R(m*1)
    # 1*m @ m*1 = 1*1 in matrix multiplication
    # but you know numpy didn't do transpose in 1d array, so here is just a
    # vector inner product to itselves
    square_sum = inner.T @ inner
    cost = square_sum / (2 * m)
    return cost

def regularized_cost(theta, X, y, l=1):
    m = X.shape[0]
    regularized_term = (l / (2 * m)) * np.power(theta[1:], 2).sum()
    return cost(theta, X, y) + regularized_term

#梯度
def gradient(theta, X, y):
    m = X.shape[0]
    #(2,12)@((12,2)@(2,1)
    inner = X.T @ (X @ theta - y)  # (m,n).T @ (m, 1) -> (n, 1)
    return inner / m

def regularized_gradient(theta, X, y, l=1):
    m = X.shape[0]
    regularized_term = theta.copy()  # same shape as theta
    regularized_term[0] = 0  # don't regularize intercept theta
    regularized_term = (l / m) * regularized_term
    return gradient(theta, X, y) + regularized_term
    
#拟合数据与参数
def linear_regression_np(X, y, l=1):
    """linear regression
    args:
        X: feature matrix, (m, n+1) # with incercept x0=1
        y: target vector, (m, )
        l: lambda constant for regularization
    return: trained parameters
    """
    # init theta
    theta = np.ones(X.shape[1])
    # train it
    res = opt.minimize(fun=regularized_cost,
                       x0=theta,
                       args=(X, y, l),
                       method='TNC',
                       jac=regularized_gradient,
                       options={'disp': True})
    return res

#绘制学习曲线
def plot_learning_curve(X, y, Xval, yval, l=0):
    training_cost, cv_cost = [], []
    m = X.shape[0]
    for i in range(1, m + 1):
        # regularization applies here for fitting parameters
        res = linear_regression_np(X[:i, :], y[:i], l=l)
        # remember, when you compute the cost here, you are computing
        # non-regularized cost. Regularization is used to fit parameters only
        tc = cost(res.x, X[:i, :], y[:i])
        cv = cost(res.x, Xval, yval)
        training_cost.append(tc)
        cv_cost.append(cv)
    plt.plot(np.arange(1, m + 1), training_cost, label='training cost')
    plt.plot(np.arange(1, m + 1), cv_cost, label='cv cost')
    plt.legend(loc=1)

#不同lamda拟合数据
l_candidate = [0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10]
training_cost, cv_cost = [], []
for l in l_candidate:
    res = linear_regression_np(X_poly, y, l)
    tc = cost(res.x, X_poly, y)
    cv = cost(res.x, Xval_poly, yval)
    training_cost.append(tc)
    cv_cost.append(cv)
    
plt.plot(l_candidate, training_cost, label='training')
plt.plot(l_candidate, cv_cost, label='cross validation')
plt.legend(loc=2)
plt.xlabel('lambda')
plt.ylabel('cost')
plt.show()
#找出使得cost最小的lamda
l_candidate[np.argmin(cv_cost)]

无监督学习

K-means(聚类)

算法流程

Repeat {
for i = 1 to m
c(i) := index (form 1 to K) of cluster centroid closest to x(i)
for k = 1 to K
μk := average (mean) of points assigned to cluster k
}
c(i): 与x(i)最近的聚类中心的索引下标
**μk 😗*表示第k个聚类中心

初始化

1.我们应该选择K<m,即聚类中心点的个数要小于所有训练集实例的数量
2。随机选择K个训练实例,然后令K个聚类中心分别与这K个训练实例相等

K-均值的一个问题在于,它有可能会停留在一个局部最小值处,而这取决于初始化的情况:为了解决这个问题,我们通常需要多次运行K-均值算法,每一次都重新进行随机初始化,最后再比较多次运行K-均值的结果,选择代价函数最小的结果。这种方法在K较小的时候(2–10)还是可行的,但是如果K较大,这么做也可能不会有明显地改善。

K的选择(肘部原则)

肘部便是最合理的聚类数量
在这里插入图片描述

代价函数(畸变函数)

J ( c ( 1 ) , . . . . , c ( m ) , μ 1 , . . . . , μ k ) = 1 m ∑ i = 1 m ∥ x ( i ) − μ c ( i ) ∥ J({c^{_{(1)}}}_{,....,}{c^{_{(m)}}}_,{\mu _{1,....,}}{\mu _k}) = \frac{1}{m}\sum\limits_{i = 1}^m {\left\| {{x^{(i)}} - {\mu _{{c^{_{(i)}}}}}} \right\|} J(c(1),....,c(m),μ1,....,μk)=m1i=1mx(i)μc(i)
注意:第一个循环是用于减小c(i)引起的代价,而第二个循环则是用于减小μi引起的代价。迭代的过程一定会是每一次迭代都在减小代价函数,不然便是出现了错误。

代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat
from IPython.display import Image
from skimage import io
from sklearn.cluster import KMeans#导入kmeans库

#第一步,找到每个点应在的中心
def find_closest_centroids(X, centroids):
#这个idx即c  
    m = X.shape[0]
    k = centroids.shape[0]
    idx = np.zeros(m)
    for i in range(m):
        min_dist = 1000000
        for j in range(k):
            dist = np.sum((X[i,:] - centroids[j,:]) ** 2)
            if dist < min_dist:
                min_dist = dist
                idx[i] = j  
    return idx
#第二步,更新这些中心点
def compute_centroids(X, idx, k):
    m, n = X.shape
    centroids = np.zeros((k, n))    
    for i in range(k):
        indices = np.where(idx == i)
        centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel()    
    return centroids
#随机初始化
def init_centroids(X, k):
    m, n = X.shape
    centroids = np.zeros((k, n))
    idx = np.random.randint(0, m, k)
    for i in range(k):
        centroids[i,:] = X[idx[i],:]    
    return centroids
    
#运行k-means
def run_k_means(X, initial_centroids, max_iters):
    m, n = X.shape
    k = initial_centroids.shape[0]
    idx = np.zeros(m)
    centroids = initial_centroids    
    for i in range(max_iters):
        idx = find_closest_centroids(X, centroids)
        centroids = compute_centroids(X, idx, k)    
    return idx, centroids

#实例:压缩图片
Image(filename='data/bird_small.png')
image_data = loadmat('data/bird_small.mat')
A = image_data['A']
# normalize value ranges
A = A / 255.
# reshape the array
X = np.reshape(A, (A.shape[0] * A.shape[1], A.shape[2]))
# randomly initialize the centroids
initial_centroids = init_centroids(X, 16)
# run the algorithm
idx, centroids = run_k_means(X, initial_centroids, 10)
# get the closest centroids one last time
idx = find_closest_centroids(X, centroids)
print(idx)
# map each pixel to the centroid value
X_recovered = centroids[idx.astype(int),:]
X_recovered.shape
X_recovered = np.reshape(X_recovered, (A.shape[0], A.shape[1], A.shape[2]))
X_recovered.shape
plt.imshow(X_recovered)
plt.show()

#运用sklearn库
# cast to float, you need to do this otherwise the color would be weird after clustring
pic = io.imread('data/bird_small.png') / 255.
io.imshow(pic)
plt.show()
# serialize data
data = pic.reshape(128*128, 3)

model = KMeans(n_clusters=16, n_init=100, n_jobs=-1)
model.fit(data)
centroids = model.cluster_centers_
C = model.predict(data)
compressed_pic = centroids[C].reshape((128,128,3))
fig, ax = plt.subplots(1, 2)
ax[0].imshow(pic)
ax[1].imshow(compressed_pic)
plt.show()

主成分析法(降维)

问题描述

问题是要将n维数据降至k维,目标是找到向量u(1),u(2),…,u(k)使得所有数据投影到这k个向量所构成的线/面上时总的投射误差最小

PCA与线性回归

在这里插入图片描述
主成分分析与线性回归是两种不同的算法。主成分分析最小化的是投射误差(Projected Error),而线性回归尝试的是最小化预测误差。线性回归的目的是预测结果,而主成分分析不作任何预测。

算法流程

1.均值归一化。我们需要计算出所有特征的均值,然后令 xj=xjj(此步是为了保证每个特征x(i)的均值都为0)。如果特征是在不同的数量级上,我们还需要将其除以标准差 σ2

2.计算协方差矩阵(covariance matrix)Σ(XTX/m):
∑ = 1 m ∑ i = 1 m ( x ( i ) ) ( x ( i ) ) T \sum = \frac{1}{m}\sum\limits_{i = 1}^m {({x^{(i)}})} {({x^{(i)}})^T} =m1i=1m(x(i))(x(i))T
Σ(nxn)

3.计算协方差矩阵Σ的特征向量(eigenvectors):
[U, S, V]= svd(sigma)

4.如果我们希望将数据从n维降至k维,我们只需要从U中选取每个特征向量的前k个元素,构成前k个特征向量,获得一个n×k维度的矩阵,我们用U_reduce表示,然后通过如下计算获得要求的新特征向量z(i): z(i)=Ureduce T*x(i) (kxn * nx1)->(kx1)

5.xappox=Ureducez,xappox≈x

主成分数量选择法

[U, S, V]= svd(sigma)
在这里插入图片描述
其中的S是一个n×n的矩阵,只有对角线上有值,而其它单元都是0,我们可以使用这个矩阵来计算平均均方误差与训练集方差的比例:
1 m ∑ i = 1 m ∥ x ( i ) − x a p p o x ∥ 2 1 m ∑ i = 1 m ∥ x ( i ) ∥ 2 = 1 − ∑ i = 1 k s i i ∑ i = 1 n s i i ≤ 1 % \frac{{\frac{1}{m}{{\sum\limits_{i = 1}^m {\left\| {{x^{(i)}} - {x_{appox}}} \right\|} }^2}}}{{\frac{1}{m}{{\sum\limits_{i = 1}^m {\left\| {{x^{(i)}}} \right\|} }^2}}} = 1 - \frac{{\sum\limits_{i = 1}^k {{s_{ii}}} }}{{\sum\limits_{i = 1}^n {{s_{ii}}} }} \le 1\% m1i=1mx(i)2m1i=1mx(i)xappox2=1i=1nsiii=1ksii1%
即:
k = 1 , . . . . n , s t o p w h e n ∑ i = 1 k s i i ∑ i = 1 n s i i ≥ 99 % k = 1,....n,stop{\rm{ when}}\frac{{\sum\limits_{i = 1}^k {{s_{ii}}} }}{{\sum\limits_{i = 1}^n {{s_{ii}}} }} \ge 99\% k=1,....n,stopwheni=1nsiii=1ksii99%

常见错误

1.将其用于减少过拟合(减少了特征的数量)。这样做非常不好,不如尝试正则化处理。原因在于主要成分分析只是近似地丢弃掉一些特征,它并不考虑任何与结果变量有关的信息,因此可能会丢失非常重要的特征。然而当我们进行正则化处理时,会考虑到结果变量,不会丢掉重要的数据。

2.默认地将主要成分分析作为学习过程中的一部分,这虽然很多时候有效果,最好还是从所有原始特征开始,只在有必要的时候(算法运行太慢或者占用太多内存)才考虑采用主要成分分析。

代码
def pca(X):
    # normalize the features
    X = (X - X.mean()) / X.std()    
    # compute the covariance matrix
    X = np.matrix(X)
    cov = (X.T * X) / X.shape[0]   
    # perform SVD
    U, S, V = np.linalg.svd(cov)    
    return U, S, V
#降维
def project_data(X, U, k):
    U_reduced = U[:,:k]
    return np.dot(X, U_reduced)# U:1*2(2,) X:n*2(n,2)
#升维
def recover_data(Z, U, k):
    U_reduced = U[:,:k]
    return np.dot(Z, U_reduced.T)
    
#展示多张图片的方法
def plot_n_image(X, n):
    """ plot first n images
    n has to be a square number
    """
    pic_size = int(np.sqrt(X.shape[1]))
    grid_size = int(np.sqrt(n))
    first_n_images = X[:n, :]
    fig, ax_array = plt.subplots(nrows=grid_size, ncols=grid_size,sharey=True, sharex=True, figsize=(8, 8))
    for r in range(grid_size):
        for c in range(grid_size):
            ax_array[r, c].imshow(first_n_images[grid_size * r + c].reshape((pic_size, pic_size)))
            plt.xticks(np.array([]))
            plt.yticks(np.array([]))

异常检测系统

数据要求

异常检测假设特征符合高斯分布,如果数据的分布不是高斯分布,异常检测算法也能够工作,但是最好还是将数据转换成高斯分布,例如使用对数函数:x=log(x+c),其中 c 为非负常数; 或者 x=x^c,c为 0-1 之间的一个分数,等方法。
(在python中,通常用np.log1p()函数,log1p就是 log(x+1),可以避免出现负数结果,反向函数就是np.expm1())

算法

对于给定的数据集 x(1),x(2),…,x(m),我们要针对每一个特征计算 μ 和 σ2 的估计值。
注意:这里是对m个数据集里的每一个特征(共n个特征)求均值和方差,公式如下:
μ j = 1 m ∑ i = 1 m x j ( i ) σ j 2 = 1 m ∑ i = 1 m ( x j ( i ) − μ j ) 2 \begin{array}{l} {\mu _j} = \frac{1}{m}\sum\limits_{i = 1}^m {{x_j}^{(i)}} \\ {\sigma _j}^2 = \frac{1}{m}{\sum\limits_{i = 1}^m {({x_j}^{(i)} - {\mu _j})} ^2} \end{array} μj=m1i=1mxj(i)σj2=m1i=1m(xj(i)μj)2
最后计算模型p(x):
p ( x ) = ∏ j = 1 n p ( x j , μ j , σ j 2 ) = ∏ j = 1 n 1 2 π σ j e − ( x j − μ j ) 2 2 σ j 2 p(x) = \prod\limits_{j = 1}^n {p({x_j},{\mu _j},{\sigma _j}^2)} = \prod\limits_{j = 1}^n {\frac{1}{{\sqrt {2\pi } {\sigma _j}}}} {e^{ - \frac{{{{({x_j} - {\mu _j})}^2}}}{{2{\sigma _j}^2}}}} p(x)=j=1np(xj,μj,σj2)=j=1n2π σj1e2σj2(xjμj)2
当p(x)<ε时,为异常
当p(x)>ε时,为正常
当p(x)=ε时,为边界

模型构建

当我们开发一个异常检测系统时,我们从带标记(异常或正常)的数据着手,我们从其中选择一部分正常数据用于构建训练集,然后用剩下的正常数据和异常数据混合的数据构成交叉检验集和测试集。

具体的评价方法如下:

  1. 根据训练集数据,我们估计特征的平均值和方差并构建p(x)函数
  2. 对交叉检验集,我们尝试使用不同的ε值作为阀值(用测试集构建的p(x)来测试),并预测数据是否异常,根据F1值或者查准率与查全率的比例来选择 ε
  3. 选出 ε 后,针对测试集进行预测,计算异常检验系统的F1值,或者查准率与查全率之比。
特征选择

一个常见的问题是一些异常的数据可能也会有较高的p(x)值,因而被算法认为是正常的。这种情况下误差分析能够帮助我们,我们可以分析那些被算法错误预测为正常的数据,观察能否找出一些问题。我们可能能从问题中发现我们需要增加一些新的特征,增加这些新特征后获得的新算法能够帮助我们更好地进行异常检测。我们通常可以通过将一些相关的特征进行组合,来获得一些新的更好的特征(异常数据的该特征值异常地大或小),

对比监督学习
异常检测监督学习
非常少量的正向类(异常数据 y=1), 大量的负向类(y=0)同时有大量的正向类和负向类
未来遇到的异常可能与已掌握的异常、非常的不同有足够多的正向类实例,足够用于训练 算法,未来遇到的正向类实例可能与训练集中的非常近似。
例如: 欺诈行为检测 生产(例如飞机引擎)检测数据中心的计算机运行状况例如:邮件过滤器 天气预报 肿瘤分类
多元高斯分布

算法:
先算出所有特征下的均值与协方差矩阵
μ = 1 m ∑ i = 1 m x ( i ) ∑ = 1 m ∑ i = 1 m ( x ( i ) − μ ) ( x ( i ) − μ ) T = 1 m ( X − μ ) ( X − μ ) T \begin{array}{l} \mu = \frac{1}{m}\sum\limits_{i = 1}^m {{x^{(i)}}} \\ \sum = \frac{1}{m}\sum\limits_{i = 1}^m {({x^{(i)}} - \mu )} {({x^{(i)}} - \mu )^T} = \frac{1}{m}(X - \mu ){(X - \mu )^T} \end{array} μ=m1i=1mx(i)=m1i=1m(x(i)μ)(x(i)μ)T=m1(Xμ)(Xμ)T
计算模型:
p ( x ) = 1 ( 2 π ) n 2 ∣ ∑ ∣ 1 2 e ( − 1 2 ( X − μ ) ∑ − 1 ( X − μ ) T ) p(x) = \frac{1}{{{{(2\pi )}^{\frac{n}{2}}}{{\left| \sum \right|}^{\frac{1}{2}}}}}{e^{( - \frac{1}{2}(X - \mu ){\sum ^{ - 1}}{{(X - \mu )}^T})}} p(x)=(2π)2n211e(21(Xμ)1(Xμ)T)
|Σ|是定矩阵

对比多元高斯分布

可以证明的是,原本的高斯分布模型是多元高斯分布模型的一个子集,即像上图中的第1、2、3,3个例子所示,如果协方差矩阵只在对角线的单位上有非零的值时,即为原本的高斯分布模型了。

原高斯分布模型多元高斯分布模型
不能捕捉特征之间的相关性 但可以通过将特征进行组合的方法来解决自动捕捉特征之间的相关性
计算代价低,能适应大规模的特征计算代价较高 训练集较小时也同样适用
必须要有 m>n,不然的话协方差矩阵 不可逆的,通常需要 m>10n 另外特征冗余(x1=x2,x4=x1+x3,线性相关)也会导致协方差矩阵不可逆
代码

此方法是让每一个特征的概率密度函数都小于某个epsilon,而非对所有特征再相乘

#正太分布函数库
from scipy import stats
#高斯分布,每一列的均值与方差
def estimate_gaussian(X):
    mu = X.mean(axis=0)
    sigma = X.var(axis=0)    
    return mu, sigma
mu, sigma = estimate_gaussian(X)
#nX2维
p = np.zeros((X.shape[0], X.shape[1]))
p[:,0] = stats.norm(mu[0], sigma[0]).pdf(X[:,0])
p[:,1] = stats.norm(mu[1], sigma[1]).pdf(X[:,1])

#训练集训练出模型后用交叉验证集选出最好的epsilon
pval = np.zeros((Xval.shape[0], Xval.shape[1]))
pval[:,0] = stats.norm(mu[0], sigma[0]).pdf(Xval[:,0])
pval[:,1] = stats.norm(mu[1], sigma[1]).pdf(Xval[:,1])
#此方法是让每一个特征的概率密度函数都小于某个epsilon,而非求和
def select_threshold(pval, yval):
    best_epsilon = 0#那个阈值
    best_f1 = 0
    f1 = 0    
    #因为有两列,所以这个只看第一列
    step = (pval.max() - pval.min()) / 1000    
    for epsilon in np.arange(pval.min(), pval.max(), step):        
    #但此处要某一数据的每一个特征都要小于epsilon
        preds = pval < epsilon        
        tp = np.sum(np.logical_and(preds == 1, yval == 1)).astype(float)
        fp = np.sum(np.logical_and(preds == 1, yval == 0)).astype(float)
        fn = np.sum(np.logical_and(preds == 0, yval == 1)).astype(float)        
        precision = tp / (tp + fp)
        recall = tp / (tp + fn)
        f1 = (2 * precision * recall) / (precision + recall)        
        if f1 > best_f1:
            best_f1 = f1
            best_epsilon = epsilon    
    return best_epsilon, best_f1
 
#绘出特征
epsilon, f1 = select_threshold(pval, yval)
 # indexes of the values considered to be outliers
outliers = np.where(p < epsilon)
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0], X[:,1])
ax.scatter(X[outliers[0],0], X[outliers[0],1], s=50, color='r', marker='o')
plt.show()

推荐系统(以用户和电影为场景)

场景介绍

在这里插入图片描述
下面引入一些标记:
nu 代表用户的数量
nm 代表电影的数量
r(i,j) 如果用户 j 给电影 i 评过分则 r(i,j)=1
y(i,j) 代表用户 j 给电影 i 的评分
mj代表用户 j 评过分的电影的总数
θ(j)用户 j 的参数向量
x(i)电影 i 的特征向量
对于用户 j 和电影 i,我们预测评分(还未评分)为:(θ(j) )T x(i)

代价函数

当给出所有电影的特征参数,求解针对所有用户的参数:
min ⁡ θ ( 1 ) , . . . , θ ( n u ) 1 2 ∑ j = 1 n u ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ j = 1 n u ∑ k = 1 n ( θ k ( j ) ) 2 \mathop {\min }\limits_{{\theta ^{(1)}},...,{\theta ^{(n_u)}}} \frac{1}{2}\sum\limits_{j = 1}^{{n_u}} {\sum\limits_{i:r(i,j) = 1} {{{({{({\theta ^{(j)}})}^T}{x^{(i)}} - {y^{(i,j)}})}^2}} } + \frac{\lambda }{2}\sum\limits_{j = 1}^{{n_u}} {\sum\limits_{k = 1}^n {{{({\theta _k}^{(j)})}^2}} } θ(1),...,θ(nu)min21j=1nui:r(i,j)=1((θ(j))Tx(i)y(i,j))2+2λj=1nuk=1n(θk(j))2
当给出所有用户的特征参数,求解针对所有电影的参数:
min ⁡ x ( 1 ) , . . . , x ( n m ) 1 2 ∑ j = 1 n m ∑ j : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ i = 1 n m ∑ k = 1 n ( x k ( i ) ) 2 \mathop {\min }\limits_{{x^{(1)}},...,{x^{({n_m})}}} \frac{1}{2}\sum\limits_{j = 1}^{{n_m}} {\sum\limits_{j:r(i,j) = 1} {{{({{({\theta ^{(j)}})}^T}{x^{(i)}} - {y^{(i,j)}})}^2}} } + \frac{\lambda }{2}\sum\limits_{i = 1}^{{n_m}} {\sum\limits_{k = 1}^n {{{({x_k}^{(i)})}^2}} } x(1),...,x(nm)min21j=1nmj:r(i,j)=1((θ(j))Tx(i)y(i,j))2+2λi=1nmk=1n(xk(i))2

协同过滤算法

如果我们既没有用户的参数,也没有电影的特征,这两种方法都不可行了。协同过滤算法可以同时学习这两者
注意:不计算θ0
代价函数:
J ( x ( 1 ) , . . . , x ( n m ) , θ ( 1 ) , . . . , θ ( n u ) ) = 1 2 ∑ ( i , j ) : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ i = 1 n m ∑ k = 1 n ( x k ( i ) ) 2 + λ 2 ∑ j = 1 n u ∑ k = 1 n ( θ k ( j ) ) 2 J({x^{(1)}},...,{x^{({n_m})}},{\theta ^{(1)}},...,{\theta ^{({n_u})}}) = \frac{1}{2}\sum\limits_{(i,j):r(i,j) = 1} {{{({{({\theta ^{(j)}})}^T}{x^{(i)}} - {y^{(i,j)}})}^2}} + \frac{\lambda }{2}\sum\limits_{i = 1}^{{n_m}} {\sum\limits_{k = 1}^n {{{({x_k}^{(i)})}^2} + } } \frac{\lambda }{2}\sum\limits_{j = 1}^{{n_u}} {\sum\limits_{k = 1}^n {{{({\theta _k}^{(j)})}^2}} } J(x(1),...,x(nm),θ(1),...,θ(nu))=21(i,j):r(i,j)=1((θ(j))Tx(i)y(i,j))2+2λi=1nmk=1n(xk(i))2+2λj=1nuk=1n(θk(j))2
梯度下降:
x k ( i ) = x k ( i ) − α ( ∑ j : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) θ k ( j ) + λ x k ( i ) ) θ k ( j ) = θ k ( j ) − α ( ∑ j : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) x k ( i ) + λ θ k ( j ) ) \begin{array}{l} {x_k}^{(i)} = {x_k}^{(i)} - \alpha (\sum\limits_{j:r(i,j) = 1} {({{({\theta ^{(j)}})}^T}{x^{(i)}} - {y^{(i,j)}}){\theta _k}^{(j)} + \lambda {x_k}^{(i)}} )\\ {\theta _k}^{(j)} = {\theta _k}^{(j)} - \alpha (\sum\limits_{j:r(i,j) = 1} {({{({\theta ^{(j)}})}^T}{x^{(i)}} - {y^{(i,j)}}){x_k}^{(i)} + \lambda {\theta _k}^{(j)}} ) \end{array} xk(i)=xk(i)α(j:r(i,j)=1((θ(j))Tx(i)y(i,j))θk(j)+λxk(i))θk(j)=θk(j)α(j:r(i,j)=1((θ(j))Tx(i)y(i,j))xk(i)+λθk(j))

算法流程:

  1. 初始 x(1),x(2),…,x(nm) , θ(1)(2),…,θ(nu)为一些随机小值
  2. 使用梯度下降算法最小化代价函数
  3. 在训练完算法后,我们预测(θ(j) )T x(i)为用户 j 给电影 i 的评分
如何推荐新电影

在这里插入图片描述

如果一个用户没有给出任何评价时的均值处理法

在这里插入图片描述
注意此处θ(5)=0,因此(θ(5))T X=0
解决:
在这里插入图片描述
如果我们要用新训练出的算法来预测评分,则需要将平均值重新加回去,预测(θ(j))T x(i)i,对于Eve,我们的新模型会认为她给每部电影的评分都是该电影的平均分。

代码
#协同过滤法的代价函数
def cost(params, Y, R, num_features, learning_rate):
    Y = np.matrix(Y)  # (1682, 943),y(i,j)
    R = np.matrix(R)  # (1682, 943),r(i,j)
    num_movies = Y.shape[0]
    num_users = Y.shape[1]   
    # reshape the parameter array into parameter matrices
    X = np.matrix(np.reshape(params[:num_movies * num_features], (num_movies, num_features)))  # (1682, 10)
    Theta = np.matrix(np.reshape(params[num_movies * num_features:], (num_users, num_features)))  # (943, 10)    
    # initializations
    J = 0
    #每一个电影,用户的每一个参数都要更新
    X_grad = np.zeros(X.shape)  # (1682, 10)
    Theta_grad = np.zeros(Theta.shape)  # (943, 10)    
    # compute the cost
    error = np.multiply((X * Theta.T) - Y, R)  # (1682, 943)
    squared_error = np.power(error, 2)  # (1682, 943)
    J = (1. / 2) * np.sum(squared_error)   
    # add the cost regularization
    J = J + ((learning_rate / 2) * np.sum(np.power(Theta, 2)))
    J = J + ((learning_rate / 2) * np.sum(np.power(X, 2)))  
    # calculate the gradients with regularization
    #对电影,用户参数theta为变量,对用户,点参数x为变量
    X_grad = (error * Theta) + (learning_rate * X)
    Theta_grad = (error.T * X) + (learning_rate * Theta)
    # unravel the gradient matrices into a single array
    grad = np.concatenate((np.ravel(X_grad), np.ravel(Theta_grad)))   
    return J, grad

#在已有模型下,把自己当作一个用户加入
ratings = np.zeros((1682, 1))
ratings[0] = 4
ratings[6] = 3
ratings[11] = 5
ratings[53] = 4
ratings[63] = 5
ratings[65] = 3
ratings[68] = 5
ratings[97] = 2
ratings[182] = 4
ratings[225] = 5
ratings[354] = 5
R = data['R']
Y = data['Y']
Y = np.append(Y, ratings, axis=1)
R = np.append(R, ratings != 0, axis=1)

#初始化用户与电影参数
movies = Y.shape[0]  # 1682
users = Y.shape[1]  # 944,多了个自己
features = 10
learning_rate = 10.
X = np.random.random(size=(movies, features))
Theta = np.random.random(size=(users, features))
params = np.concatenate((np.ravel(X), np.ravel(Theta)))

#均值归一化,只对平了分的算均值
Ymean = np.zeros((movies, 1))
Ynorm = np.zeros((movies, users))
for i in range(movies):
    idx = np.where(R[i,:] == 1)[0]
    Ymean[i] = Y[i,idx].mean()
    Ynorm[i,idx] = Y[i,idx] - Ymean[i]
#计算模型
from scipy.optimize import minimize
fmin = minimize(fun=cost, x0=params, args=(Ynorm, R, features, learning_rate), method='CG', jac=True, options={'maxiter': 100})

#给自己预测一下自己喜欢的电影
predictions = X * Theta.T 
my_preds = predictions[:, -1] + Ymean
#按数从小到大的索引排,此处置逆
idx = np.argsort(my_preds, axis=0)[::-1]
print("Top 10 movie predictions:")
for i in range(10):
    j = int(idx[i])
    print('Predicted rating of {0} for movie {1}.'.format(str(float(my_preds[j])), movie_idx[j]))

大规模数据集的处理

是否需要大规模数据集(学习曲线)

首先应该做的事是去检查一个这么大规模的训练集是否真的必要,也许我们只用1000个训练集也能获得较好的效果,我们可以绘制学习曲线来帮助判断。
在这里插入图片描述
左图过拟合,适合
右图欠拟合,不适合

随机梯度下降法(SGD)

算法:

1.首先对数据进行洗牌
2.执行算法:
r e p e a t ( u s u a l l y b e t w e e n 1 − 10 ) { f o r i = 1 : m { θ j = θ j − α ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ( f o r j = 0 : n ) } } \begin{array}{l} repeat(usually{\rm{ between 1 - 10}})\left\{ {} \right.\\ for{\rm{ i = 1:m}}\left\{ {} \right.\\ {\theta _j} = {\theta _j} - \alpha ({h_\theta }({x^{(i)}}) - {y^{(i)}}){x_j}^{(i)}\\ (for{\rm{ j = 0:n)}}\\ \left. {} \right\}\\ \left. {} \right\} \end{array} repeat(usuallybetween110){fori=1:m{θj=θjα(hθ(x(i))y(i))xj(i)(forj=0:n)}}

对比批量梯度下降

随机梯度下降算法在每一次计算之后便更新参数 θ ,而不需要首先将所有的训练集求和,在梯度下降算法还没有完成一次迭代时,随机梯度下降算法便已经走出了很远。但是这样的算法存在的问题是,不是每一步都是朝着”正确”的方向迈出的。因此算法虽然会逐渐走向全局最小值的位置,但是可能无法站到那个最小值的那一点,而是在最小值点附近徘徊

α选择与收敛

在随机梯度下降中,我们在每一次更新 θ 之前都计算一次代价,然后每x次迭代后,求出这x次对训练实例**(选中的要计算的那些固定的实例)**计算代价的平均值,然后绘制这些平均值与x次迭代的次数之间的函数图表。
在这里插入图片描述
当我们绘制这样的图表时,可能会得到一个颠簸不平但是不会明显减少的函数图像(如上面左下图中蓝线所示)。我们可以增加α来使得函数更加平缓,也许便能看出下降的趋势了(如上面左下图中红线所示);或者可能函数图表仍然是颠簸不平且不下降的(如洋红色线所示),那么我们的模型本身可能存在一些错误。
如果我们得到的曲线如上面右下方所示,不断地上升,那么我们可能会需要选择一个较小的学习率α。
α更新准则
α=const1/(iterationNumber+const2)

小批量梯度下降

批量梯度下降:一次迭代要用m个输入
随机梯度下降:一次迭代只用一个输入
小批量梯度下降:小批量梯度下降算法是介于批量梯度下降算法和随机梯度下降算法之间的算法,每计算常数b次训练实例,便更新一次参数 θ

算法:

r e p e a t { f o r i = 1 : m { θ j = θ j − α 1 b ∑ k = i i + b − 1 ( h θ ( x ( k ) ) − y ( k ) ) x j ( k ) ( f o r j = 0 : n ) i = i + b } } \begin{array}{l} repeat\left\{ {} \right.\\ for{\rm{ i = 1:m}}\left\{ {} \right.\\ {\theta _j} = {\theta _j} - \alpha \frac{1}{b}\sum\limits_{k = i}^{i + b - 1} {({h_\theta }({x^{(k)}}) - {y^{(k)}}){x_j}^{(k)}} \\ (for{\rm{ j = 0:n)}}\\ {\rm{i = i + b}}\\ \left. {} \right\}\\ \left. {} \right\} \end{array} repeat{fori=1:m{θj=θjαb1k=ii+b1(hθ(x(k))y(k))xj(k)(forj=0:n)i=i+b}}
通常我们会令 b 在 2-100 之间。这样做的好处在于,我们可以用向量化的方式来循环 b个训练实例,如果我们用的线性代数函数库比较好,能够支持平行处理,那么算法的总体表现将不受影响(与随机梯度下降相同)

在线学习机制

一个算法来从中学习的时候来模型化问题在线学习算法指的是对数据流而非离线的静态数据集的学习

算法

在线学习的算法与随机梯度下降算法有些类似,我们对单一的实例进行学习,而非对一个提前定义的训练集进行循环。
Repeat forever (as long as the website is running) {
Get (x,y) corresponding to the current user (parameter :θj)
θj:=θj-α(hθ (x)-y) xj
(for j=0:n)
}
一旦对一个数据的学习完成了,我们便可以丢弃该数据,不需要再存储它了。这种方式的好处在于,我们的算法可以很好的适应用户的倾向性,算法可以针对用户的当前行为不断地更新模型以适应该用户。

映射简化和数据并行

**映射简化:**如果我们能够将我们的数据集分配给多台计算机,让每一台计算机处理数据集的一个子集,然后我们将计所的结果汇总在求和
具体而言,如果任何学习算法能够表达为,对训练集的函数的求和,那么便能将这个任务分配给多台计算机(或者同一台计算机的不同CPU 核心),以达到加速处理的目。
很多高级的线性代数函数库已经能够利用多核CPU的多个核心来并行地处理矩阵运算,这也是算法的向量化实现如此重要的缘故(比调用循环快)
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值