目录
数学表达
求解代价函数 J(θ0,θ1) J ( θ 0 , θ 1 ) 中的 θ0,θ1 θ 0 , θ 1 使得 J(θ0,θ1) J ( θ 0 , θ 1 ) 最小。
- θ0=0,θ1=0 θ 0 = 0 , θ 1 = 0
- 重复同时更新 θj:=θj−α∂∂θjJ(θ0,θ1)(j=0,1) θ j := θ j − α ∂ ∂ θ j J ( θ 0 , θ 1 ) ( j = 0 , 1 ) ,直到 θj θ j 不再改变
其中的 θ0,θ1 θ 0 , θ 1 表示假设的线性函数中的两个参数, α α 表示学习速率
胡思乱想时刻
- 计算机如何表示这个求偏导数的过程呢?
结合假设函数 hθ(x) h θ ( x ) 与代价函数 J(θ0,θ1) J ( θ 0 , θ 1 ) 有
θ0=θ0−α∂∂θ0J(θ0,θ1)=θ0−α∂∂θ0(12m∑mi=1(hθ(xi)−yi)2)=θ0−αm∑mi=1((hθ(xi)−yi)∂∂θ0hθ(xi))=θ0−αm∑mi=1((hθ(xi)−yi)∂∂θ0(θ0+θ1xi))=θ0−αm∑mi=1(hθ(xi)−yi) θ 0 = θ 0 − α ∂ ∂ θ 0 J ( θ 0 , θ 1 ) = θ 0 − α ∂ ∂ θ 0 ( 1 2 m ∑ i = 1 m ( h θ ( x i ) − y i ) 2 ) = θ 0 − α m ∑ i = 1 m ( ( h θ ( x i ) − y i ) ∂ ∂ θ 0 h θ ( x i ) ) = θ 0 − α m ∑ i = 1 m ( ( h θ ( x i ) − y i ) ∂ ∂ θ 0 ( θ 0 + θ 1 x i ) ) = θ 0 − α m ∑ i = 1 m ( h θ ( x i ) − y i )
同理得到 θ1 θ 1
θ1=θ1−αm∑mi=1xi(hθ(xi)−yi) θ 1 = θ 1 − α m ∑ i = 1 m x i ( h θ ( x i ) − y i )
推广开去:
θi=θi−αm∑m−1k=0xki(hθ(xk)−yk) θ i = θ i − α m ∑ k = 0 m − 1 x i k ( h θ ( x k ) − y k ) (其中的 k k 表示第几组训练数据,与上面式子中的等价,而此式子中的 i i 表示第几项)
将代入上式得
θi=θi−(αm∑n−1j=0∑m−1k=0θjxkjxki−αm∑m−1k=0ykxki) θ i = θ i − ( α m ∑ j = 0 n − 1 ∑ k = 0 m − 1 θ j x j k x i k − α m ∑ k = 0 m − 1 y k x i k )
//Batch Gradient Descent
const int N = 30, M = 100000;
typedef struct Data {
double x[N + 1], y;
} TrainingData;
TrainingData TD[M];
void partial (double alpha, double *p, double *theta, int n, TrainingData *TD, int m) {
//此处偏导数的求解,依据上面最后一个式子
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j)
for (int k = 0; k < m; ++k)
p[i] += alpha * theta[j] * TD[k].x[j] * TD[k].x[i] / m;
for (int k = 0; k < m; ++k)
p[i] -= alpha * TD[k].y * TD[k].x[i] / m;
}
}
void GDA(double *theta, int n, TrainingData *TD, int m) {
double alpha = 1, p[n];
//此处的alpha没有动态处理,p数组用于记录偏导数
for (int i= 0; i < m; ++i) //初始化
TD[i].x[0] = 1;
for (int i = 0; i < n; ++i) //初始化
p[i] = 0, theta[i] = 0;
do {
bool isLoop = false; //控制循环是否终止
partial(alpha, p, theta, n, TD, m); //求偏导数
for (int i = 0; i < n; ++i) {
if (p[i] != 0) { //判断偏导数是否为零
theta[i] -= p[i];
isLoop = true;
}
}
}while(isLoop);
}
关于 θj=θj−α∂∂θjJ(θ0,θ1) θ j = θ j − α ∂ ∂ θ j J ( θ 0 , θ 1 ) 是如何能够在 α α 取值合理的情况下,保证趋于最小值呢?
导数能够表示一个函数的在该点处的切线斜率。
当导数值越小时,切线斜率的绝对值也就越小。
当导数值等于0时,切线斜率就为0,此时取得最优。
同时还有考虑到,导数的正负表示在最优点的右侧和左侧(因为代价函数是只有最小值,不存在最大值)。
那么导数的正负就可以,引导 θj θ j 的取值是增大还是减少,最终达到导数为零的情况。学习速率 α α 如何取值?
如果 α α 取的值很大,那么可能无法收敛于最小值;如果 α α 取的很小,则将增大运算次数。
由此得出, α α 的取值一定不是一个定值。
再次考虑,导数与斜率的关系,当接近最优点时,斜率就会变小,此时学习速率就需要减少。