DeepLearning学习笔记
大纲
Logisitic Regression逻辑回归
1. 二分分类
2. 符号约定
3. 逻辑回归
4. 梯度下降法
5. Vectorization向量化
6. Python Broadcasting广播
Logisitic Regression逻辑回归
二分分类
输入对象--->提取特征向量\(x\)(维度为\(n\))--->分类器--->输出预测标签\(y\)(\(1\)或\(0\))
符号约定
训练样本\((x,y)\)----\(x\)代表\(n\)维的特征向量, \(y\)代表标签(\(0\)或\(1\)), \(m\)个样本即为\((x_1,y_2),(x_2,y_2), ... ,(x_m,y_m)\)
训练样本集\(X\)----\(X = (x_1, x_2, ... , x_m)\), 维度为\((n * m)\)
标签集\(Y\)----\(Y = (y_1, y_2, ... , y_m)\), 维度为\((1 * m)\)
回归函数\(z\)----\(z = w^Tx + b\)
微分符号----\(dz = \frac{dJ}{dz}, dw = \frac{\partial J}{\partial w}, db = \frac{\partial J}{\partial b}\)
逻辑回归
- 思路: 特征向量\(x\)--->算法--->预测标签\(\hat y\)(概率值\(P\in (0, 1)\))
- 参数: \(w\)(\(n\)维向量), \(b\)(实数\(R\))
-
逻辑回归算法: 用于计算预测输出值\(\hat y\)
\[\hat y = \sigma(w^Tx + b)\]
\[\sigma(z) = \frac{1}{e^{-z} + 1}, z = w^Tx + b\]
由图示可见
- 当\(z\to \infty\), \(\sigma(z)\to 1\)
- 当\(z\to 0\), \(\sigma(z)\to 0\)
-
Loss Function损失函数: 用于衡量预测输出值\(\hat y\)与标签\(y\)有多接近(衡量单个训练样本的表现)
\[L(\hat y, y) = - (ylg\hat y + (1 - y)lg(1 - \hat y))\]
\(L\)值越小, 则预测值与真实值越接近, 即损失损越小
分析可知:
- \(y = 1\)时, \(L(\hat y, y) = -lg\hat y\), \(L\to 0 \Rightarrow \hat y\to 1\)
- \(y = 0\)时, \(L(\hat y, y) = - lg(1 - \hat y)\), \(L\to 0 \Rightarrow \hat y\to 0\)
-
Cost Function成本函数: 用于衡量全体训练样本(样本集)的表现, 即总成本
\[J(w, b) = \frac{1}{m}\sum_{i = 1}^m L(\hat y_i, y_i) = -\frac{1}{m}\sum_{i = 1}^m [y_ilg\hat y_i + (1 - y_i)lg(1 - \hat y_i)]\]
梯度下降法
梯度下降法用于得到回归算法中合适的参数\(w\)和\(b\), 即让\(J(w, b)\)尽量小的\(w\)和\(b\)
\(J(w, b)\)是凹函数, 当\(w\)和\(b\)都仅为一个实数时, \(J(w, b)\)如图
设定参数\(w\)和\(b\)的初始值, 获得对应的\(J(w, b)\)函数, 令
\[w' = w - \alpha\frac{\partial J(w,b)}{\partial w}\]
\[b' = b - \alpha\frac{\partial J(w,b)}{\partial b}\]
其中\(\alpha\)是学习率。然后令\(w = w', b = b'\), 使\(w\)和\(b\)的值得到更新, 通过不断重复这个步骤, 最终将得到使\(J(w, b)\)趋于最小值时的\(w, b\)
根据导数计算可得
\[dz_i = \hat y_i -y_i, dw = \frac{1}{m}\sum_{i=1}^m x_idz_i\]
\[db = \frac{1}{m}\sum_{i=1}^m dz_i\]
Vectorization向量化
处理庞大的数据样本时应避免使用非向量化算法, 如for loop, 下面是向量化和非向量化算法在相同运算量下的速度差别
import numpy as np #导入numpy
import time
a = np.random.rand(1000000) #两个一百万维的矩阵
b = np.random.rand(1000000)
tic = time.time() #计算前的时间
c = np.dot(a,b) #向量化运算
toc = time.time() #计算后的时间
print(c)
print("Vectorized version: " + str(1000*(toc-tic)) + "ms") #计算用时
c = 0
tic = time.time()
for i in range(1000000): #非向量化运算
c += a[i]*b[i]
toc = time.time()
print(c)
print("for loop: " + str(1000*(toc-tic)) + "ms")
输出结果
249919.47604
Vectorized version: 1.5935897827148438ms
249919.47604
for loop: 330.3234577178955ms
np.function()
这样的内置函数能充分利用并行化去进行更快的计算, 将多个数据整合成一个向量矩阵, 从而实现并行化运算, 这就是并行的主要思想
-
逻辑回归的向量化:
现在将逻辑回归的数学形式转换为向量化的结构
由向量乘法运算可知\(Z = (z_1, z_2, ..., z_m) = (w^Tx_1 + b, w^Tx_2 + b, ..., w^Tx_m + b)= w^TX + (b, b, ..., b) = np.dot(w.T,x) + b\)
\(A = \sigma(Z)\)
\(dZ = (dz_1, dz_2, ..., dz_m) = (\hat y_1 - y_1, \hat y_2 - y_2, ..., \hat y_m - y_m) = A - Y\) (求导可得)
\(db = \frac{1}{m}\sum_{i = 1}^m dz_i = \frac{1}{m} np.sum(dZ)\) (求导可得)
\(dw = \frac{1}{m}\sum_{i = 1}^m x_idz_i = \frac{1}{m}XdZ^T\) (求导可得)
\(w' = w - \alpha dw\)
\(b' = b - \alpha db\) (更新\(w\)和\(b\))这样就将原本需要两次for循环的结构高度向量化了, 如果需要多次更新\(w\)和\(b\)值, 则还是需要使用for循环
Python Broadcasting广播
Python中的广播特性能够简化计算的输入, 让代码运行更快。 其主要用来处理对一个矩阵的所有行或所有列做相同的变换的情况, 下面是一些例子
\[\begin{pmatrix} 2 \\ 0 \\ 3 \\ 7 \end{pmatrix} \qquad + \qquad 300 \qquad \Rightarrow \qquad \begin{pmatrix} 2 \\ 0 \\ 3 \\ 7 \end{pmatrix} \qquad + \qquad \begin{pmatrix} 300 \\ 300 \\ 300 \\ 300 \end{pmatrix}\]
\[\begin{pmatrix} 1 & 2 & 3 \\ 2 & 3 & 6 \end{pmatrix} + \begin{pmatrix} 300 & 500 & 900 \end{pmatrix} \Rightarrow \begin{pmatrix} 1 & 2 & 3 \\ 2 & 3 & 6 \end{pmatrix} + \begin{pmatrix} 300 & 500 & 900 \\ 300 & 500 & 900 \end{pmatrix}\]
\[\begin{pmatrix} 7 & 5 & 3 \\ 2 & 4 & 6 \end{pmatrix} \quad + \quad \begin{pmatrix} 200 \\ 700 \end{pmatrix} \quad \Rightarrow \quad \begin{pmatrix} 7 & 5 & 3 \\ 2 & 4 & 6 \end{pmatrix} \quad + \quad \begin{pmatrix} 200 & 200 & 200 \\ 700 & 700 & 700 \end{pmatrix}\]
可以在NumPy文档中的“广播“中了解到更广义的用法
KNN: 是一个模型, 和迭代过程是不一样的概念
图片数据: 三个矩阵数据,分别用于存储图像所有像素的R,G,B值
SIMD指令: 并行化指令, 单指令流多数据流
numpy向量说明: 避免使用\(r(A)\)为\(1\)的行向量, 或用reshape
将其转化为列向量; 使用assert(a.shape == (m,m))
确保_a_是一个向量