Course1-Week3:
https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Supervised%20Machine%20Learning%20Regression%20and%20Classification/week3
机器学习笔记(四)
- 1️⃣逻辑回归(logistic regression)
- 🎗️代价函数
- 🎗️梯度下降
- 2️⃣决策边界(decision boundary)
- 3️⃣过拟合(overfit)
- 4️⃣正则化(regularization)
- 🎗️线性回归的正则方法
- 🎗️逻辑回归的正则方法
1️⃣逻辑回归(logistic regression)
🎈分类问题作为有监督学习的一种,在它能根据输入的特征 x \bm{x} x (特征向量),来从有限的分类中预测出属于哪个分类,例如:将电子邮件识别为垃圾邮件还是非垃圾邮件或确定肿瘤为恶性还是良性等这些问题,这两个问题都只有两种结果,可以是二分类问题,如果有多种结果则为多分类问题。
🎈如下是根据肿瘤的大小去进行肿瘤类型的分类(1表示为恶性,0表示为良性),对于这种情景可以看出,用线性回归去拟合图像不是个很好的选择。
😞类似这种情况使用线性回归来拟合看上去是有点糟糕,拟合的很不合适,而且对于分类问题,它受数据的影响太大了,导致它拟合的效果会更差。
😃而逻辑回归就排上用场了,它是通过构造出一个 s i g m o i d sigmoid sigmoid 函数,来形成这样的曲线,可以很好的拟合分类问题。
s i g m o i d : g ( z ) = 1 1 + e − z , 0 < g ( z ) < 1 sigmoid: g(z)=\frac 1 {1+e^{-z}}, 0<g(z)<1 sigmoid:g(z)=1+e−z1,0<g(z)<1
✨逻辑回归模型的构造过程:通过 s i g m o i d sigmoid sigmoid 函数将线性转为非线性,将值域映射到了 0~1 之间,用于分类问题。本质就是找一个更拟合数据情况的函数去套用(线性回归就是这么找出来的)。
f w ⃗ , b ( x ⃗ ) = g ( z ) = g ( w ⃗ ⋅ x ⃗ + b ) = 1 1 + e − ( w ⃗ ⋅ x ⃗ + b ) f_{\vec w,b}(\vec x)=g(z)=g({\vec w} \cdot {\vec x+b})= \frac 1 {1+e^{-(\vec w \cdot \vec x+b)}} fw,b(x)=g(z)=g(w⋅x+b)=1+e−(w⋅x+b)1
对于逻辑回归输出可以把它视做概率, f w ⃗ , b ( x ⃗ ) = 0.7 f_{\vec w,b}(\vec x)=0.7 fw,b(x)=0.7 时可以认为对于特征 x \bm x x 预测出的肿瘤为恶性的可能为70%,逻辑回归的输出值越大,肿瘤为恶性的可能性就越大。
对于一组分类数据,可以看出逻辑回归的拟合效果是不错的。
🎗️代价函数
🎈代价函数的定义, L L L 为损失函数(Loss function):
J ( w , b ) = 1 m ∑ i = 1 m L ( f w ⃗ , b ( x ⃗ ( i ) ) , y ( i ) ) J(w,b)=\frac 1 {m} \sum_{i=1}^{m}L(f_{\vec w,b}(\vec x^{(i)}),y^{(i)}) J(w,b)=m1i=1∑mL(fw,b(x(i)),y(i))
在线性回归中我们使用了平方误差成本作为损失函数,其代价函数 J ( w ⃗ , b ) J(\vec w,b) J(w,b) 图像为一个下凸的形状,可以通过梯度下降收敛到一个非常好的参数。
🎈squared error cost function:
J ( w , b ) = 1 2 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) 2 J(w,b)=\frac 1 {2m} \sum_{i=0}^{m-1}(f_{ w,b}(x^{(i)})-y^{(i)})^2 J(w,b)=2m1i=0∑m−1(fw,b(x(i))−y(i))2
在线性回归中: f w , b ( x ( i ) ) = w x ( i ) + b 在线性回归中:f_{ w,b}(x^{(i)})=wx^{(i)}+b 在线性回归中:fw,b(x(i))=wx(i)+b
而对于逻辑回归来说直接使用平方误差代价函数,会导致 J ( w ⃗ , b ) J(\vec w,b) J(w,b) 有多个局部最小值,使用梯度下降很难找到一个好的参数。
✨首先直接给出逻辑回归的代价函数定义,再分析:
J ( w ⃗ , b ) = 1 m ∑ i = 1 m L ( f w ⃗ , b ( x ⃗ ( i ) ) , y ( i ) ) = { − l o g ( f w ⃗ , b ( x ⃗ ( i ) ) ) if y ( i ) = 1 − l o g ( 1 − f w ⃗ , b ( x ⃗ ( i ) ) ) if y ( i ) = 0 J(\vec w,b)=\frac 1 m \sum_{i=1}^mL(f_{\vec w,b}(\vec x^{(i)}),y^{(i)})= \begin{cases}-log(f_{\vec w,b}(\vec x^{(i)})) & \text{if } y^{(i)} = 1 \\ -log(1-f_{\vec w,b}(\vec x^{(i)})) & \text{if } y^{(i)} = 0 \end{cases} J(w,b)=m1i=1∑mL(fw,b(x(i)),y(i))={−log(fw,b(x(i)))−log(1−fw,b(x(i)))if y(i)=1if y(i)=0
在逻辑回归中: f w , b ( x ( i ) ) = 1 1 + e − ( w ⃗ ⋅ x ⃗ + b ) 在逻辑回归中:f_{ w,b}(x^{(i)})= \frac 1 {1+e^{-(\vec w \cdot \vec x+b)}} 在逻辑回归中:fw,b(x(i))=1+e−(w⋅x+b)1
🎈先从损失函数 L ( y ^ ( i ) , y ( i ) ) L(\hat y^{(i)},y^{(i)}) L(y^(i),y(i)) 入手,由于逻辑回归其函数在平方误差损失函数中不凸,我们将其映射到一个凸的 l o g log log 函数中,有以下定义和图像性质:
这种函数可以很好的达到我们想要的效果,当 y ( i ) = 1 y^{(i)}=1 y(i)=1 时,逻辑回归函数的值越接近 1 时,有着越接近于 0 的代价;而逻辑回归函数的值越接近于 0 时,有着接近 ∞ \infty ∞ 的代价,例如将一个恶性肿瘤预测为良性,其代价是巨大的,这样的代价还能很好的去惩罚模型,让机器不要出现这种预测。
当 y ( i ) = 0 y^{(i)}=0 y(i)=0 时,该损失函数亦然达到我们想要的效果。
我们可以看出这种函数是行得通的,所以对于逻辑回归问题的代价函数为:
✨其图像非常适合梯度下降,它没有平台、局部最小值或不连续性。
🤓我们其实还可以进一步简化逻辑回归的成本函数,因为 y y y 并不能取 0 或 1 外的任何值,可以先简写它的损失函数:
L ( f w ⃗ , b ( x ⃗ ( i ) ) , y ( i ) ) = − y ( i ) l o g ( f w ⃗ , b ( x ⃗ ( i ) ) ) − ( 1 − y ( i ) ) l o g ( 1 − f w ⃗ . b ( x ⃗ ( i ) ) ) L(f_{\vec w,b}(\vec x^{(i)}),y^{(i)})=-y^{(i)}log(f_{\vec w,b}(\vec x^{(i)}))-(1-y^{(i)})log(1-f_{\vec w.b}(\vec x^{(i)})) L(fw,b(x(i)),y(i))=−y(i)log(fw,b(x(i)))−(1−y(i))log(1−fw.b(x(i)))
看起来是个很复杂的形式,但是当只能考虑 y ( i ) y^{(i)} y(i) 等于 0 或 1 的情况下时,该方程就变会了原来的两段式。
✨简化后的代价函数为:
J ( w ⃗ , b ) = 1 m ∑ i = 1 m [ L ( f w ⃗ , b ( x ⃗ ( i ) ) , y ( i ) ) ] = − 1 m ∑ i = 1 m [ y ( i ) l o g ( f w ⃗ , b ( x ⃗ ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − f w ⃗ . b ( x ⃗ ( i ) ) ) ] \begin{align*} J(\vec w,b)&=\frac 1 m \sum_{i=1}^{m}[L(f_{\vec w,b}(\vec x^{(i)}),y^{(i)})] \\ &=-\frac 1 m \sum_{i=1}^{m}[y^{(i)}log(f_{\vec w,b}(\vec x^{(i)}))+(1-y^{(i)})log(1-f_{\vec w.b}(\vec x^{(i)}))] \end{align*} J(w,b)=m1i=1∑m[L(fw,b(x(i)),y(i))]=−m1i=1∑m[y(i)log(fw,b(x(i)))+(1−y(i))log(1−fw.b(x(i)))]
🎗️梯度下降
前面学过了梯度下降法的公式,而逻辑回归的梯度下降同理,只是其成本函数 J J J 有所不同了,将其代入即可。
🧐可以看到求出来的偏导数和线性回归求出来的长相一样,但是其实函数 f f f 的定义已经改变了,在线性回归中, f w , b ( x ( i ) ) = w x ( i ) + b f_{ w,b}(x^{(i)})=wx^{(i)}+b fw,b(x(i))=wx(i)+b,而在逻辑回归中 f w , b ( x ( i ) ) = 1 1 + e − ( w ⃗ ⋅ x ⃗ + b ) f_{ w,b}(x^{(i)})= \frac 1 {1+e^{-(\vec w \cdot \vec x+b)}} fw,b(x(i))=1+e−(w⋅x+b)1,两者并不是一个东西,请注意这一点。
🌹再来直观感受一下逻辑回归的梯度下降过程:
代码上可以通过 sklearn.linear_model.LogisticRegression 导入逻辑回归模型去拟合数据。
from sklearn.linear_model import LogisticRegressionlr_model = LogisticRegression()
lr_model.fit(X, y)
2️⃣决策边界(decision boundary)
🎈由于逻辑回归模型 f w ⃗ , b ( x ⃗ ) f_{\vec w,b}(\vec x) fw,b(x) 输出的是 ( 0 , 1 ) (0,1) (0,1) 连续的值,而预测值 y ^ \hat y y^ 为 0 或 1,由可以结合对模型输出概率上的理解,去定义一个阈值,当 f w ⃗ , b ( x ⃗ ) ≥ 阈值, y ^ = 1 f_{\vec w,b}(\vec x) \geq 阈值,\hat y=1 fw,b(x)≥阈值,y^=1;当 f w ⃗ , b ( x ⃗ ) < 阈值, y ^ = 0 f_{\vec w,b}(\vec x) < 阈值,\hat y=0 fw,b(x)<阈值,y^=0。 若设定阈值为 0.5 0.5 0.5,当 f w ⃗ , b ( x ⃗ ) ≥ 0.5 f_{\vec w,b}(\vec x) \ge 0.5 fw,b(x)≥0.5 时,即 w ⃗ ⋅ x ⃗ + b ≥ 0 \vec w \cdot \vec x+b \ge 0 w⋅x+b≥0,有 y ^ = 1 \hat y=1 y^=1;当 f w ⃗ , b ( x ⃗ ) < 0.5 f_{\vec w,b}(\vec x) < 0.5 fw,b(x)<0.5 时,即 w ⃗ ⋅ x ⃗ + b < 0 \vec w \cdot \vec x+b<0 w⋅x+b<0 时,有 y ^ = 0 \hat y=0 y^=0。
此定义又让我们专注于 w ⃗ ⋅ x ⃗ + b \vec w \cdot \vec x+b w⋅x+b 上来, 而此时 w ⃗ ⋅ x ⃗ + b = 0 \vec w \cdot \vec x+b=0 w⋅x+b=0 即为决策边界。
🎈linear decision boundary:
🎈Non-linear decision boundaries:
3️⃣过拟合(overfit)
🎈对于回归问题,如下有三图,🌹可以看到左图用一个线性函数去拟合数据,但是表现的并不怎么好,因为对于数据集来说,明显可以看出 s i z e size size 越大, p r i c e price price 增加的速度越慢,图像应该越平缓,所以左图这种情况被称为欠拟合(underfit) 或 高偏差(high bias);🌹中间的函数图像很好的拟合了数据集,而且具有通用性,因为我们可以想到对于一个新数据它应该也能做出一个合适的预测,即具有泛化性(generalization);🌹而在右图中,该曲线完美的经过了每个数据集,甚至损失为 0,但它只是为了数据集而生的,脱离了数据集毫无作用,可以看到图中对于一个相对较大的 s i z e size size 居然给出了更小的 p r i c e price price ,所以它不具有通用性,不能对新数据进行预测(这将毫无意义),这种情况则成为过拟合(overfit) 或 高方差(high variance)。
🎈在分类问题中,同样会有这种问题。
✨为了避免过拟合这种情况,有以下的解决方法:
① 添加足够多的数据,让图像具有泛化性。
② 特征选择,过拟合的一个原因就是特征选择的太多,导致函数成为一个复杂的多项式,我们可以进行特征的选择,只选择其中与 y y y 值最相关的特征,可以有效地解决一些过拟合问题。
③ 正则化(Regularization)
正则化是通过减小参数 w j w_j wj 来减轻特征对函数值的影响来防止过拟合,相较于 ② 它并不直接消除特征,还是采取更温和的方式去调整。
4️⃣正则化(regularization)
🎈正则化是机器学习中的一种技术,主要用于减少模型的复杂度,防止过拟合,提高模型的泛化能力,还可以通过正则化来惩罚模型的参数,使得模型变得更简单。正则化就是说给代价函数加上一些限制(正则化项),通过这种限制去规范他们再接下来的循环迭代中,不要自我膨胀。
先改写一下代价函数,给它加上后面两项 1000 w 3 2 1000w_3^2 1000w32 和 1000 w 4 2 1000w_4^2 1000w42 ,这时如果想要最小化代价函数,由于后面两项过大的影响,需要让 w 3 w_3 w3 和 w 4 w_4 w4 非常小,这样又变相惩罚的函数 f f f 的参数 w 3 , w 4 w_3,w_4 w3,w4 ,使得高次数的项影响变小,这样变相让函数缓解了过拟合问题。
🧐顺着这个思路,假设我们不知道各个特征的影响程度,就想让机器自己去惩罚对应的特征项系数 w j w_j wj 去解决过拟合问题,这就是正则化。我们给代价函数加入一个正则化项,里面有所有的 w j w_j wj,由于为了最小化代价,机器会惩罚所有的 w j w_j wj。
✨正则化项为: λ 2 m ∑ j = 1 m w j 2 , λ 为正则化参数 \frac \lambda {2m} \sum_{j=1}^m w_j^2 \,, \, \lambda 为正则化参数 2mλj=1∑mwj2,λ为正则化参数
🤓对于正则化参数 λ \lambda λ,它的选择可以是为了实现损失函数和保持小的 w j w_j wj 这两者的平衡。一个过小的正则化参数 λ \lambda λ 会让正则化参数形同虚设,没法解决过拟合问题;而一个过大的正则化参数 λ \lambda λ 会让 w j w_j wj 被惩罚的过于小,导致欠拟合,所以需要选择一个好的 λ \lambda λ 避免出现这两种情况。
🎗️线性回归的正则方法
线性回归使用了正则化的代价函数和梯度下降如下:
如图,当学习率 α = 0.01 \alpha=0.01 α=0.01 ,正则化参数 λ = 1 \lambda=1 λ=1,而样本数量 m = 50 m=50 m=50 时可以看到我们将 w j w_j wj 缩小为了 0.9998 w j 0.9998w_j 0.9998wj,这就是正则化的惩罚作用,比起正则化之前直接在 w j w_j wj 上的梯度下降来说,我们的惩罚使得 w j w_j wj 变得更小。
def compute_cost_linear_reg(X, y, w, b, lambda_ = 1):"""Computes the cost over all examplesArgs:X (ndarray (m,n): Data, m examples with n featuresy (ndarray (m,)): target valuesw (ndarray (n,)): model parameters b (scalar) : model parameterlambda_ (scalar): Controls amount of regularizationReturns:total_cost (scalar): cost """m = X.shape[0]n = len(w)cost = 0.for i in range(m):f_wb_i = np.dot(X[i], w) + b #(n,)(n,)=scalar, see np.dotcost = cost + (f_wb_i - y[i])**2 #scalar cost = cost / (2 * m) #scalar reg_cost = 0for j in range(n):reg_cost += (w[j]**2) #scalarreg_cost = (lambda_/(2*m)) * reg_cost #scalartotal_cost = cost + reg_cost #scalarreturn total_cost
🎗️逻辑回归的正则方法
在逻辑回归中,我们也可以使用正则化方法:
def compute_cost_logistic_reg(X, y, w, b, lambda_ = 1):"""Computes the cost over all examplesArgs:Args:X (ndarray (m,n): Data, m examples with n featuresy (ndarray (m,)): target valuesw (ndarray (n,)): model parameters b (scalar) : model parameterlambda_ (scalar): Controls amount of regularizationReturns:total_cost (scalar): cost """m,n = X.shapecost = 0.for i in range(m):z_i = np.dot(X[i], w) + b #(n,)(n,)=scalar, see np.dotf_wb_i = sigmoid(z_i) #scalarcost += -y[i]*np.log(f_wb_i) - (1-y[i])*np.log(1-f_wb_i) #scalarcost = cost/m #scalarreg_cost = 0for j in range(n):reg_cost += (w[j]**2) #scalarreg_cost = (lambda_/(2*m)) * reg_cost #scalartotal_cost = cost + reg_cost #scalarreturn total_cost #scalar