机器学习算法--线性回归

1、代价函数

J(\theta ) = \frac{1}{{2{\text{m}}}}\sum\limits_{i = 1}^m {{{({h_\theta }({x^{(i)}}) - {y^{(i)}})}^2}}

其中: {h_\theta }(x) = {\theta _0} + {\theta _1}{x_1} + {\theta _2}{x_2} + ...

下面就是要求出theta,使代价最小,即代表我们拟合出来的方程距离真实值最近

共有m条数据,其中{{{({h_\theta }({x^{(i)}}) - {y^{(i)}})}^2}}代表我们要拟合出来的方程到真实值距离的平方,平方的原因是因为可能有负值,正负可能会抵消。

前面有系数2的原因是下面求梯度是对每个变量求偏导,2可以消去。注意X是真实数据前加了一列1,因为有theta(0)。

2、梯度下降算法

代价函数对{{\theta _j}}求偏导得到:
\frac{{\partial J(\theta )}}{{\partial {\theta j}}} = \frac{1}{m}\sum\limits{i = 1}^m {[({h_\theta }({x^{(i)}}) - {y^{(i)}})x_j^{(i)}]}

所以对theta的更新可以写为:
{\theta j} = {\theta j} - \alpha \frac{1}{m}\sum\limits{i = 1}^m {[({h\theta }({x^{(i)}}) - {y^{(i)}})x_j^{(i)}]}

其中\alpha为学习速率,控制梯度下降的速度,一般取0.01,0.03,0.1,0.3.....

为什么梯度下降可以逐步减小代价函数

假设函数f(x)

泰勒展开:f(x+△x)=f(x)+f'(x)*△x+o(△x)

令:△x=-α*f'(x) ,即负梯度方向乘以一个很小的步长α

△x代入泰勒展开式中:f(x+x)=f(x)-α*[f'(x)]²+o(△x)

可以看出,α是取得很小的正数,[f'(x)]²也是正数,所以可以得出:f(x+△x)<=f(x)

所以沿着负梯度放下,函数在减小,多维情况一样。

3、均值归一化

目的是使数据都缩放到一个范围内,便于使用梯度下降算法

{x_i} = \frac{{{x_i} - {\mu _i}}}{{{s_i}}}

其中 {{\mu _i}} 为所有此feture数据的平均值

{{s_i}}可以是最大值-最小值,也可以是这个feature对应的数据的标准差。

全部代码:

#-*- coding: utf-8 -*-
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)    # 解决windows环境下画图汉字乱码问题


def linearRegression(alpha=0.01,num_iters=400):
    print u"加载数据...\n"
    
    data = loadtxtAndcsv_data("data.txt",",",np.float64)  #读取数据
    X = data[:,0:-1]      # X对应0到倒数第2列                  
    y = data[:,-1]        # y对应最后一列  
    m = len(y)            # 总的数据条数
    col = data.shape[1]      # data的列数
    
    X,mu,sigma = featureNormaliza(X)    # 归一化
    plot_X1_X2(X)         # 画图看一下归一化效果
    
    X = np.hstack((np.ones((m,1)),X))    # 在X前加一列1
    
    print u"\n执行梯度下降算法....\n"
    
    theta = np.zeros((col,1))
    y = y.reshape(-1,1)   #将行向量转化为列
    theta,J_history = gradientDescent(X, y, theta, alpha, num_iters)
    
    plotJ(J_history, num_iters)
    
    return mu,sigma,theta   #返回均值mu,标准差sigma,和学习的结果theta
    
   
# 加载txt和csv文件
def loadtxtAndcsv_data(fileName,split,dataType):
    return np.loadtxt(fileName,delimiter=split,dtype=dataType)

# 加载npy文件
def loadnpy_data(fileName):
    return np.load(fileName)

# 归一化feature
def featureNormaliza(X):
    X_norm = np.array(X)            #将X转化为numpy数组对象,才可以进行矩阵的运算
    #定义所需变量
    mu = np.zeros((1,X.shape[1]))   
    sigma = np.zeros((1,X.shape[1]))
    
    mu = np.mean(X_norm,0)          # 求每一列的平均值(0指定为列,1代表行)
    sigma = np.std(X_norm,0)        # 求每一列的标准差
    for i in range(X.shape[1]):     # 遍历列
        X_norm[:,i] = (X_norm[:,i]-mu[i])/sigma[i]  # 归一化
    
    return X_norm,mu,sigma

# 画二维图
def plot_X1_X2(X):
    plt.scatter(X[:,0],X[:,1])
    plt.show()


# 梯度下降算法
def gradientDescent(X,y,theta,alpha,num_iters):
    m = len(y)      
    n = len(theta)
    
    temp = np.matrix(np.zeros((n,num_iters)))   # 暂存每次迭代计算的theta,转化为矩阵形式
    
    
    J_history = np.zeros((num_iters,1)) #记录每次迭代计算的代价值
    
    for i in range(num_iters):  # 遍历迭代次数    
        h = np.dot(X,theta)     # 计算内积,matrix可以直接乘
        temp[:,i] = theta - ((alpha/m)*(np.dot(np.transpose(X),h-y)))   #梯度的计算
        theta = temp[:,i]
        J_history[i] = computerCost(X,y,theta)      #调用计算代价函数
        print '.',      
    return theta,J_history  

# 计算代价函数
def computerCost(X,y,theta):
    m = len(y)
    J = 0
    
    J = (np.transpose(X*theta-y))*(X*theta-y)/(2*m) #计算代价J
    return J

# 画每次迭代代价的变化图
def plotJ(J_history,num_iters):
    x = np.arange(1,num_iters+1)
    plt.plot(x,J_history)
    plt.xlabel(u"迭代次数",fontproperties=font) # 注意指定字体,要不然出现乱码问题
    plt.ylabel(u"代价值",fontproperties=font)
    plt.title(u"代价随迭代次数的变化",fontproperties=font)
    plt.show()

# 测试linearRegression函数
def testLinearRegression():
    mu,sigma,theta = linearRegression(0.01,400)
    #print u"\n计算的theta值为:\n",theta
    #print u"\n预测结果为:%f"%predict(mu, sigma, theta)
    
# 测试学习效果(预测)
def predict(mu,sigma,theta):
    result = 0
    # 注意归一化
    predict = np.array([1650,3])
    norm_predict = (predict-mu)/sigma
    final_predict = np.hstack((np.ones((1)),norm_predict))
    
    result = np.dot(final_predict,theta)    # 预测结果
    return result
    
    
if __name__ == "__main__":
    testLinearRegression()

4、或者,直接使用scikit-learn库中的线性模型实现

#-*- coding: utf-8 -*-
import numpy as np
from sklearn import linear_model
from sklearn.preprocessing import StandardScaler    #引入归一化的包

def linearRegression():
    print u"加载数据...\n"
    data = loadtxtAndcsv_data("data.txt",",",np.float64)  #读取数据
    X = np.array(data[:,0:-1],dtype=np.float64)      # X对应0到倒数第2列                  
    y = np.array(data[:,-1],dtype=np.float64)        # y对应最后一列  
        
    # 归一化操作
    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_  # 又名bias偏置,若设置为False,则为0
    print result            # 预测结果


# 加载txt和csv文件
def loadtxtAndcsv_data(fileName,split,dataType):
    return np.loadtxt(fileName,delimiter=split,dtype=dataType)

# 加载npy文件
def loadnpy_data(fileName):
    return np.load(fileName)




if __name__ == "__main__":
    linearRegression()

5、结果

代价随迭代次数的变化
enter description here

猜你喜欢

转载自blog.csdn.net/rongpeisheng666/article/details/81740118