gradicent descent

注: 图片以后再补全好了,囧...

最近在学习机器学习的知识,首先看到的是递归下降法进行线性拟合.
从形式上理解这货其实蛮简单的,我用废话描述一番要解决的问题好了.

有那么一堆点散落在x,y坐标轴上,放眼望去,好像是围绕着一条直线分布的.好吧,要解决的问题就是求出那条近似直线的方程.

按照ng的课程来说的话,已知一个地区的部分房价数据(比如下面的)
x=[2104,1416,1534,852,1940]
y=[400,232,178,121,370]
x表示面积,y表示房价,估算该地区另一套房子(比如1314平米吧)的合理价位.

假设hθ表示估计的价位,那么为了保证估计的价格尽可能的准确,要使得|hθ-y|这个值尽量的小.为此定义,

J(θ)=1/(2*m)*Σi = 1_to_m[hθ(xi)-y(i)]**2

如果用上面的x,y来算的话,上式中的m就是5,因为x有5个数据.

为了满足J(θ)尽可能小,可以取其倒数为零时候的值,即

dJ(θ)/dθ = (hθ(x)-y)*x

P.S. 此时表忘记了,虽然是要满足J(θ)最小,即dJ(θ)/dθ的值为零,这样就能求出窝们需要的位置量θ!

大致的流程就是酱紫,那么,如何估算h(θ)呢?
因为只有一组x且从图形来看是线性的,所以可以,

hθ(x) = θ0+θ1*x1

这个式子可以写成

hθ(x) = θ0*x0+θ1*x1 其中x0为1

或者

hθ(x) = Σi = 1_to_n[θi*xi] = θ.T * x

P.S. 上面出现了m和n,按照给出的数据来说,m为5,n为2.

用python来实现

(参考了下stackoverflow的一篇问答,不过有些改动)

首先导入需要的包包

import random
import numpy as np
from matplotlib import pyplot as plt

第一步 产生数据

x_from, x_to = 1, 100
y_from, y_to = 25, 140
num = 100
var = 2
x, y = genLinearData(num, x_from, x_to, y_from, y_to, var)

这段代码是围绕着一条直线产生点用的.直线的斜率为(140-25)/(100-1).采样点为100,引入噪音量基数为2

genLinearData的实现如下,

def genLinearData(num, x1, x2, y1, y2, variance):
    x_1 = np.linspace(x1, x2, num)
    x = np.zeros(shape=(num, 2))
    y = np.linspace(y1, y2, num)
    for i in range(num):
        x[i][0] = 1
        x[i][1] = x_1[i]
        y[i] = y[i] + random.uniform(0, 1) * variance
    return x, y

返回的x, y即为用于计算θ用的x和y, 当然x矩阵的第一列为1(这对应前面说的x0)

获取m和n

m, n = np.shape(x)

计算θ

numIterations = 50000
alpha = 0.0001
theta = np.ones(n) #n=2
theta[0]=25
theta[1]=1
theta = gradientDescent(x, y, theta, alpha, m, numIterations)

numIterations是递归次数,alpha是递归下降的步进值,numIterations从θ0+θ1*x1可以看出θ0是与y轴的交点,θ1是斜率.

P.S. 选值尽量与实际的接近些,否则很容易不准的说(至少窝实验的是这样,也可能错掉了.

gradientDescent实现方法

def gradientDescent(x, y, theta, alpha, m, numIterations):
    xTrans = x.transpose()
    for i in range(0, numIterations):
        hypothesis = np.dot(x, theta)
        loss = hypothesis - y 
        cost = np.sum(loss ** 2) / (2 * m)
        print("Iteration %d | Cost: %f" % (i, cost)) 
        gradient = np.dot(xTrans, loss) / m
        theta = theta - alpha * gradient
    return theta

运行时可以看到,cost是下降的,并收敛于某个比较小的点.

构建曲线

xx = np.linspace(x_from, x_to, num)
yy = theta[0] + theta[1] * xx

输出,

plt.scatter(x[:,1], y, c='r')
plt.plot(xx, yy, c='y')
plt.show()

dameng
16 声望2 粉丝

引用和评论

0 条评论