胡话

主要给自己备忘,放博客方便查看,代码梯度下降部分主要参考文末链接,正规方程法代码自己写的,虽然很简单但算是机器学习的“Hello World”,有点小激动。

虽然之前也看着《机器学习实战》也写出过梯度下降,但那时候理解不深,并没有太多欣喜,现在对它理解程度进了一步,再写才感觉是真的第一次。

我是懒人,所以不太愿意花太多时间在博客上,所以看官可能不会太方便,但我注释尽量写全呼了,复制粘贴看应该还好。

代码

梯度下降

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: CK
# Date: 2021/1/11
import os
import sys
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

abs_path = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.append(os.path.dirname(abs_path))


class GradientDescent:
    def __init__(self):
        pass

    @staticmethod
    def cost(x, y, theta):
        """
        计算损失函数
        :param x: 数据集
        :param y: 标签
        :param theta: 参数
        :return:
        """
        # 误差计算公式
        return sum(np.power((np.dot(x, theta.T) - y), 2)) / (2 * len(x))

    def gradient_descent(self, x, y, theta, alpha, epoch=1000):
        """
        梯度下降
        :param x: 训练集
        :param y: 标签
        :param theta: 参数
        :param alpha: 学习率
        :param epoch: 迭代次数
        :return:
        """
        cost = np.zeros(epoch)  # 为之后绘图作数据准备
        m = x.shape[0]  # 数据集数量
        for i in range(epoch):
            # 梯度下降公式
            theta -= (alpha / m) * (x.dot(theta.T) - y).T.dot(x)
            cost[i] = self.cost(x, y, theta)
        return theta, cost

    def run(self):
        """主入口"""
        data = pd.read_csv(os.path.join(abs_path, 'ex1', 'ex1data1.txt'),
                           names=['Population', 'Profit'], header=None)
        # 添加x_0
        data.insert(0, 'Ones', 1)
        column_num = data.shape[1]
        # 获取x、y数列
        x = np.array(data.iloc[:, : column_num-1].values)
        y = np.array(data.iloc[:, column_num-1: column_num].values)
        # 初始化theta
        theta = np.zeros([1, 2])
        print(self.cost(x, y, theta))
        final_theta, cost = self.gradient_descent(x, y, theta, 0.01)
        # print(final_theta, cost)
        final_cost = self.cost(x, y, final_theta)
        print(final_theta, final_cost)
        population = np.linspace(data.Population.min(), data.Population.max(), 100)
        # 计算相应值以便之后编制曲线
        profit = final_theta[0, 0] + (final_theta[0, 1] * population)
        # matplotlib绘图
        fig, ax = plt.subplots(figsize=(8, 6))
        ax.plot(population, profit, 'r', label='Prediction')
        ax.scatter(data['Population'], data['Profit'], label='TrainingData')  # 原始数据散点
        ax.legend(loc=4)
        ax.set_xlabel('Population')
        ax.set_ylabel('Profit')
        ax.set_title('PredictionProfit')
        plt.show()


def main():
    gd = GradientDescent()
    gd.run()


if __name__ == '__main__':
    main()

正规方程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: CK
# Date: 2021/1/12
import os
import sys
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

abs_path = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.append(os.path.dirname(abs_path))
from gradient_descent import GradientDescent


class NormalEquation:
    def __init__(self):
        pass

    @staticmethod
    def normal_equation(x, y):
        """
        正规方程法
        :param x: 数据集
        :param y: 标签
        :return:
        """
        return np.linalg.pinv(x.T.dot(x)).dot(x.T).dot(y)

    def run(self, x, y, theta):
        """主入口"""
        # 调用之前写的梯度下降法,得到的theta
        gd = GradientDescent()
        final_theta, cost = gd.gradient_descent(x, y, theta, 0.4)
        print(final_theta, gd.cost(x, y, theta))
        # 绘制学习曲线,1000是因为梯度下降默认迭代数量
        plt.plot(range(1000), cost)
        plt.show()
        # 通过正规方程法直接计算得到theta
        ne_theta = self.normal_equation(x, y)
        print(ne_theta.T, gd.cost(x, y, ne_theta.T))


def main():
    ne = NormalEquation()
    data = pd.read_csv(os.path.join(abs_path, 'ex1', 'ex1data2.txt'),
                       names=['Size', 'Bedrooms', 'Price'], header=None)
    column_num = data.shape[1]
    x = data.iloc[:, : column_num-1]
    y = data.iloc[:, column_num-1: column_num]
    # 数据归一化
    # x_normalization = (x - x.min()) / (x.max() - x.min())
    x_normalization = (x - x.mean()) / x.std()
    x_normalization.insert(0, 'Ones', 1)
    x_set = np.array(x_normalization.values)
    y_set = np.array(y.values)
    theta = np.zeros([1, column_num])
    ne.run(x_set, y_set, theta)


if __name__ == '__main__':
    main()

数据集

ex1data1.txt

6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166
5.7107,3.2522
14.164,15.505
5.734,3.1551
8.4084,7.2258
5.6407,0.71618
5.3794,3.5129
6.3654,5.3048
5.1301,0.56077
6.4296,3.6518
7.0708,5.3893
6.1891,3.1386
20.27,21.767
5.4901,4.263
6.3261,5.1875
5.5649,3.0825
18.945,22.638
12.828,13.501
10.957,7.0467
13.176,14.692
22.203,24.147
5.2524,-1.22
6.5894,5.9966
9.2482,12.134
5.8918,1.8495
8.2111,6.5426
7.9334,4.5623
8.0959,4.1164
5.6063,3.3928
12.836,10.117
6.3534,5.4974
5.4069,0.55657
6.8825,3.9115
11.708,5.3854
5.7737,2.4406
7.8247,6.7318
7.0931,1.0463
5.0702,5.1337
5.8014,1.844
11.7,8.0043
5.5416,1.0179
7.5402,6.7504
5.3077,1.8396
7.4239,4.2885
7.6031,4.9981
6.3328,1.4233
6.3589,-1.4211
6.2742,2.4756
5.6397,4.6042
9.3102,3.9624
9.4536,5.4141
8.8254,5.1694
5.1793,-0.74279
21.279,17.929
14.908,12.054
18.959,17.054
7.2182,4.8852
8.2951,5.7442
10.236,7.7754
5.4994,1.0173
20.341,20.992
10.136,6.6799
7.3345,4.0259
6.0062,1.2784
7.2259,3.3411
5.0269,-2.6807
6.5479,0.29678
7.5386,3.8845
5.0365,5.7014
10.274,6.7526
5.1077,2.0576
5.7292,0.47953
5.1884,0.20421
6.3557,0.67861
9.7687,7.5435
6.5159,5.3436
8.5172,4.2415
9.1802,6.7981
6.002,0.92695
5.5204,0.152
5.0594,2.8214
5.7077,1.8451
7.6366,4.2959
5.8707,7.2029
5.3054,1.9869
8.2934,0.14454
13.394,9.0551
5.4369,0.61705

ex1data2.txt

2104,3,399900
1600,3,329900
2400,3,369000
1416,2,232000
3000,4,539900
1985,4,299900
1534,3,314900
1427,3,198999
1380,3,212000
1494,3,242500
1940,4,239999
2000,3,347000
1890,3,329999
4478,5,699900
1268,3,259900
2300,4,449900
1320,2,299900
1236,3,199900
2609,4,499998
3031,4,599000
1767,3,252900
1888,2,255000
1604,3,242900
1962,4,259900
3890,3,573900
1100,3,249900
1458,3,464500
2526,3,469000
2200,3,475000
2637,3,299900
1839,2,349900
1000,1,169900
2040,4,314900
3137,3,579900
1811,4,285900
1437,3,249900
1239,3,229900
2132,4,345000
4215,4,549000
2162,4,287000
1664,2,368500
2238,3,329900
2567,4,314000
1200,3,299000
852,2,179900
1852,4,299900
1203,3,239500

参考链接

吴恩达机器学习课后习题ex1

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐