机器学习(一):线性回归

一、问题描述

给定数据集D=\left\{\left(\boldsymbol{x}_{1}, y_{1}\right),\left(\boldsymbol{x}_{2}, y_{2}\right), \ldots,\left(\boldsymbol{x}_{m}, y_{m}\right)\right\} 其中\boldsymbol{x}_{i}=\left(x_{i 1};x_{i 2} ; \ldots ; x_{i d} ), y_{i} \in \mathbb{R}\right.
线性回归(linear regression)试图学得f\left(\boldsymbol{x}_{i}\right)=\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}_{i}+b,使得f\left(\boldsymbol{x}_{i}\right) \simeq y_{i}
代价函数为J(\theta)=\frac{1}{2 m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2},其中h_{\theta}(x)=\theta_{0}+\theta_{1} x_{1}+\theta_{2} x_{2}+\ldots,求解\boldsymbol \theta,使代价函数最小,即代表拟合出来的方程距离真实值最近的过程称为线性回归的参数估计(parameter estimation)。
采用梯度下降法求解\boldsymbol \theta参数。代价函数对\boldsymbol \theta求偏导,可以得到:\frac{\partial J(\theta)}{\partial \theta_{j}}=\frac{1}{m} \sum_{i=1}^{m}\left[\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}\right]

由此\boldsymbol \theta 更新方式为:\theta_{j}=\theta_{j}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left[\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}\right]其中\alpha为学习率(learning rate)。

二、实现过程

该部分使用一个案例来实现线性回归的过程,使用前两列数据来预测最后一列数据,数据格式和散点图如下图所示。本文采用原始手动实现和scikit-learn包两种方式实现这一过程。

部分数据
原始数据散点图

2.1、手动实现

  1. 需要用的包和数据输入。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D

data_file = 'data.csv'
  1. 主函数,实现整个线性回归的过程
def LinearRegression(alpha=0.01,iters=500):
    # initial data
    data = pd.read_csv(data_file)
    data = np.array(data.values[:,:])
    X = data[:,:-1]  # all roww, all col except the last
    Y = data[:,-1]   # all row, the last col
    plot_source(X,Y)
    row = len(Y)
    col = data.shape[1]
    Y = Y.reshape(-1,1)     # reshape row vector to col vector
    X,mu,sigma = Standardiza(X)   # data normalization
    X = np.hstack((np.ones((row,1)),X))   # add one col 1 before X

    theta = np.zeros((col,1))
    theta,J_history = GradientDescent(X,Y,theta,alpha,iters)
    plot_J(J_history,iters)

    return mu,sigma,theta
  1. 数据标准化的过程
def Standardiza(matrix):
    norm_m = np.array(matrix)
    mu = np.zeros((1,matrix.shape[1]))
    sigma = np.zeros((1,matrix.shape[1]))
    mu = np.mean(norm_m,0)  # mean of each col, 0 for col
    sigma = np.std(norm_m,0) # standard deviation of each col

    for i in range(matrix.shape[1]):
        norm_m[:,i] = (norm_m[:,i]-mu[i])/sigma[i]
    return norm_m,mu,sigma
  1. 梯度下降的计算过程
def GradientDescent(X,Y,theta,alpha,iters):
    m,n = len(Y),len(theta)
    temp = np.matrix(np.zeros((n,iters)))
    J_history = np.zeros((iters,1))

    for i in range(iters):
        h = np.dot(X,theta)
        theta -=  ((alpha/m)*(np.dot(np.transpose(X),h-Y)))
        temp[:,i] = theta
        J_history[i] = Cost(X,Y,theta)
    return theta,J_history
  1. 代价函数和预测函数的计算过程
def Cost(X,Y,theta):
    m = len(Y)
    J = 0
    J = (np.dot(np.transpose(np.dot(X,theta) - Y),(np.dot(X,theta) - Y)))/(2*m)

    return J

def Predict(mu,sigma,theta):
    result = 0
    predict = np.array([1650,3])
    norm_p = (predict-mu)/sigma
    final_p = np.hstack((np.ones((1)),norm_p))
    result = np.dot(final_p,theta)
    print(result)

6.绘图函数

def plot_source(X,Y):
    fig = plt.figure(1)
    ax = Axes3D(fig)
    ax.set_xlabel('x[0]')
    ax.set_ylabel('x[1]')
    ax.set_zlabel('y')
    ax.scatter(X[:,0],X[:,1],Y)
    plt.show()

def plot_J(J_history,iters):
    x = np.arange(1,iters+1)
    plt.plot(x,J_history)
    plt.xlabel('iterations')
    plt.ylabel('cost value')
    plt.show()
  1. 主函数的调用
if __name__=='__main__':
    mu,sigma,theta = LinearRegression(0.01,500)
    Predict(mu,sigma,theta)

下图为代价函数的曲线变化,可见随着迭代进行代价函数值逐渐减小并收敛到一个较小值,测试数据的预测结果为263871.04186383。
代价函数变化曲线

拟合直线

2.2、调用scikit-learn线性回归包

调用sklearn的linear_model中的LinearRegression模型。输出结果为:coef_: [110248.92165868 -6226.22670553]intercept_: 339119.45652173914predict result: [292195.80095132]

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import linear_model
from sklearn.preprocessing import StandardScaler

data_file = 'data.csv'

def Linear_Regression(alpha=0.01,iters=500):
    # initial data
    data = pd.read_csv(data_file)
    data = np.array(data.values[:,:],np.float64)
    X = data[:,:-1]  # all roww, all col except the last
    Y = data[:,-1]   # all row, the last col

    scaler = StandardScaler()
    scaler.fit(X)
    x_train = scaler.transform(X)
    x_test = scaler.transform(np.array([[1650,3]]))

    model = linear_model.LinearRegression()
    model.fit(x_train,Y)

    result = model.predict(x_test)
    print(model.coef_)      # Coefficient of the features 
    print(model.intercept_)   # offset
    print(result)

if __name__=='__main__':
    Linear_Regression()

获取原始数据请点击这里,感谢lawlite19的贡献。

三、数据归一化和标准化

归一化(normalization) 是使数据都缩放到[0,1]区间。这样能够消除量纲,加快收敛,也能提高精度。常用表达式为:x_{\text { norm }}^{(i)}=\frac{x_{i}-x_{\min }}{x_{\max }-x_{\min }}

标准化(standardization) 是通过特征的平均值和标准差,将特征缩放成一个标准的正态分布,缩放后均值为0,方差为1。但即使数据不服从正态分布,也可以用此法。特别适用于数据的最大值和最小值未知,或存在孤立点。标准化是为了方便数据的下一步处理,而进行的数据缩放等变换,不同于归一化,并不是为了方便与其他数据一同处理或比较。表达式为:x_{s t d}^{(i)}=\frac{x_{i}-\mu_{x}}{\delta_{x}} 其中\mu_{x}表示特征的均值, \delta_{x}表示特征的标准差。

参考资料

[1] https://github.com/lawlite19/MachineLearning_Python
[2] 周志华著. 机器学习. 北京:清华大学出版社,2016
[3] https://www.jianshu.com/p/3761bad01053
[4] https://www.zhihu.com/question/20467170

相知无远近,万里尚为邻。 ——— 张九龄《送韦城李少府》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345