• 梯度下降法解决线性回归


    一:梯度下降法推导公式:

    二:当训练集为1维时

    #进行数据分析所需库,可以看做是对numpy工具的补充
    import pandas as pd
    import numpy as np
    
    #应该把Seaborn视为matplotlib的补充,作图所用工具,在大多数情况下使用seaborn就能做出很具有吸引力的图,而使用matplotlib就能制作具有更多特色的图
    import seaborn as sns
    import matplotlib.pyplot as plt
    #设置绘画的图标格式和颜色
    sns.set(context="notebook", style="whitegrid", palette="dark")
    #读取数据并赋予列名,此时df共有两列,列名分别为population和profit
    df = pd.read_csv('ex1data1.txt', names=['population', 'profit'])
    
    
    def get_x(df):
        #ones:格式化为一个m列的全为1的向量
        ones = pd.DataFrame({'ones':np.ones(len(df))})
        #将date格式化为ones向量右边加上df矩阵的矩阵
        data = pd.concat([ones, df], axis=1)
        #返回data矩阵的前两列,返回m * 2的矩阵
        return data.iloc[:, :-1].as_matrix() # 这个操作返回 ndarray,不是矩阵
    
    
    def get_y(df):
        #返回df矩阵的最后一列,返回m × 1的向量
        return np.array(df.iloc[:, -1])
    
    
    def normalize_feature(df):
        # 特征缩放,对df中的两列数据分别进行特征缩放 :(x - x平均值)/ x方差
        return df.apply(lambda column: (column - column.mean())/column.std())
    
    
    X = get_x(df)
    print(X.shape, type(X)) #X为m × 2的矩阵
    y = get_y(df)
    print(y.shape, type(y)) #y为m × 1的向量
    
    theta = np.zeros(X.shape[1])#X.shape[1]=2,代表特征数n X.shape(0) = 97;X.shape(1) = 2;将theta初始化为2行的零向量(列向量)
    
    
    def lr_cost(theta, X, y):
    #     """
    #     计算theta固定时,此时的代价函数值
    #     X: R(m*n), m 样本数, n 特征数
    #     y: R(m)
    #     theta : R(n), 线性回归的参数
    #     """
        m = X.shape[0]#m为样本数
    
        #X矩阵和theta矩阵的点积所得矩阵(m × 1) - 矩阵y(m × 1)
        inner = X @ theta - y  # R(m*1),X @ theta等价于X.dot(theta)
    
        #square_sum为inner的每个元素平方之和,即二范数
        square_sum = inner.T @ inner
    
        #得到此时代价函数的值
        cost = square_sum / (2 * m)
    
        return cost
    
    
    #将代价函数对theta求导,即求梯度
    def gradient(theta, X, y):
        #m为样本数
        m = X.shape[0]
    
        #这里的inner为代价函数对theta求导的结果
        inner = X.T @ (X @ theta - y)  # (m,n).T @ (m, 1) -> (n, 1),X @ theta等价于X.dot(theta)
    
        return inner / m
    
    #梯度下降函数
    def batch_gradient_decent(theta, X, y, epoch, alpha=0.01):
    #   拟合线性回归,返回参数和代价
    #     epoch: 批处理的轮数
    #     alpha: theta移动的步长
    #     """
    
        #得到初始theta时的代价
        cost_data = [lr_cost(theta, X, y)]
    
        # 拷贝一份,不和原来的theta混淆
        _theta = theta.copy()
    
        #开始迭代epoch次
        for _ in range(epoch):
            #根据当前梯度更新theta
            _theta = _theta - alpha * gradient(_theta, X, y)
            #记录此时的代价
            cost_data.append(lr_cost(_theta, X, y))
    
        return _theta, cost_data
    
    
    #迭代500次求最小代价和所对应的theta
    epoch = 500
    final_theta, cost_data = batch_gradient_decent(theta, X, y, epoch)
    
    # 计算最终的代价
    lr_cost(final_theta, X, y)
    
    #画出代价函数值变化图
    #可以看到从第二轮代价数据变换很大,接下来平稳了
    ax = sns.tsplot(cost_data, time=np.arange(epoch+1))
    ax.set_xlabel('epoch')
    ax.set_ylabel('cost')
    plt.show()
    
    
    b = final_theta[0] # intercept,Y轴上的截距
    m = final_theta[1] # slope,斜率
    
    #画出原数据点和线性回归的最终结果
    plt.scatter(df.population, df.profit, label="Training data")
    plt.plot(df.population, df.population*m + b, label="Prediction")
    plt.legend(loc=2)
    plt.show()

    三:当训练集为多维时

    当训练集为多维时只需将上述代码稍作改动,完整代码如下:

    #进行数据分析所需库,可以看做是对numpy工具的补充
    import pandas as pd
    import numpy as np
    
    #应该把Seaborn视为matplotlib的补充,作图所用工具,在大多数情况下使用seaborn就能做出很具有吸引力的图,而使用matplotlib就能制作具有更多特色的图
    import seaborn as sns
    import matplotlib.pyplot as plt
    
    #设置绘画的图标格式和颜色
    sns.set(context="notebook", style="whitegrid", palette="dark")
    #读取数据并赋予列名,此时df共有两列,列名分别为population和profit
    df = pd.read_csv('ex1data2.txt', names=['square', 'bedrooms', 'price'])
    df.head()
    
    
    
    def get_x(df):
        #ones:格式化为一个m列的全为1的向量
        ones = pd.DataFrame({'ones':np.ones(len(df))})
        #将date格式化为ones向量右边加上df矩阵的矩阵
        data = pd.concat([ones, df], axis=1)
        #返回data矩阵的前两列,返回m * 2的矩阵
        return data.iloc[:, :-1].as_matrix() # 这个操作返回 ndarray,不是矩阵
    
    
    def get_y(df):
        #返回df矩阵的最后一列,返回m × 1的向量
        return np.array(df.iloc[:, -1])
    
    
    def normalize_feature(df):
        # 特征缩放,对df中的两列数据分别进行特征缩放 :(x - x平均值)/ x方差
        return df.apply(lambda column: (column - column.mean())/column.std())
    
    data = normalize_feature(df) #特征缩放
    
    X = get_x(data)
    print(X.shape, type(X)) #X为m × 2的矩阵
    y = get_y(data)
    print(y.shape, type(y)) #y为m × 1的向量
    
    theta = np.zeros(X.shape[1])#X.shape[1]=2,代表特征数n X.shape(0) = 97;X.shape(1) = 2;将theta初始化为2行的零向量(列向量)
    
    
    def lr_cost(theta, X, y):
    #     
    #     计算theta固定时,此时的代价函数值
    #     X: R(m*n), m 样本数, n 特征数
    #     y: R(m)
    #     theta : R(n), 线性回归的参数
    #     
        m = X.shape[0]#m为样本数
    
        #X矩阵和theta矩阵的点积所得矩阵(m × 1) - 矩阵y(m × 1)
        inner = X @ theta - y  # R(m*1),X @ theta等价于X.dot(theta)
    
        #square_sum为inner的每个元素平方之和,即二范数
        square_sum = inner.T @ inner
    
        #得到此时代价函数的值
        cost = square_sum / (2 * m)
    
        return cost
    
    
    #将代价函数对theta求导,即求梯度
    def gradient(theta, X, y):
        #m为样本数
        m = X.shape[0]
    
        #这里的inner为代价函数对theta求导的结果
        inner = X.T @ (X @ theta - y)  # (m,n).T @ (m, 1) -> (n, 1),X @ theta等价于X.dot(theta)
    
        return inner / m
    
    
    #梯度下降函数
    def batch_gradient_decent(theta, X, y, epoch, alpha=0.01):
    #   拟合线性回归,返回参数和代价
    #     epoch: 批处理的轮数
    #     alpha: theta移动的步长
    #     
    
        #得到初始theta时的代价
        cost_data = [lr_cost(theta, X, y)]
    
        # 拷贝一份,不和原来的theta混淆
        _theta = theta.copy()
    
        #开始迭代epoch次
        for _ in range(epoch):
            #根据当前梯度更新theta
            _theta = _theta - alpha * gradient(_theta, X, y)
            #记录此时的代价
            cost_data.append(lr_cost(_theta, X, y))
    
        return _theta, cost_data
    
    
    base = np.logspace(-1, -5, num=4)
    candidate = np.sort(np.concatenate((base, base*3)))
    
    epoch = 50
    
    fig, ax = plt.subplots(figsize=(16, 9))
    
    for alpha in candidate:
        _, cost_data = batch_gradient_decent(theta, X, y, epoch, alpha=alpha)
        ax.plot(np.arange(epoch+1), cost_data, label=alpha)
    
    ax.set_xlabel('epoch', fontsize=18)
    ax.set_ylabel('cost', fontsize=18)
    ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    ax.set_title('learning rate', fontsize=18)
    plt.show()
    '''
    #画出代价函数值变化图
    #可以看到从第二轮代价数据变换很大,接下来平稳了
    ax = sns.tsplot(cost_data, time=np.arange(epoch+1))
    ax.set_xlabel('epoch')
    ax.set_ylabel('cost')
    plt.show()
    '''

    转载于:https://www.cnblogs.com/qiang-wei/p/9823110.html

  • 相关阅读:
    SqlServer丢失.ldf日志文件,附加数据库mdf文件的解决办法
    NetCore+Consul服务注册+Ocelot网关配置
    docker 配置apollo
    docker部署nacos
    金蝶云星空自定义WebApi接口开发和调用
    挂载错误:系统不支持 cifs 文件系统
    staticmethod classmethod
    Kitex源码阅读——脚手架代码是如何通过命令行生成的(一)
    Kitex源码阅读——脚手架代码是如何通过命令行生成的(二)
    GO的日志库log竟然这么简单!
  • 原文地址:https://www.cnblogs.com/twodog/p/12135760.html
Copyright © 2020-2023  润新知