《封号码罗》数据分析与人工智能之sklearn梯度下降(九)

第一部分

import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt

# 如果有截距,求解时,需要梯度下降法求解w和b

# 什么是梯度??? 梯度就是导数
# 梯度下降是求解最大值,最小值最快的速度
# 导数是函数变化率最快的方向

# 平均变化率:(f(x2)-f(x1))/(x2-x1)称为函数f(x)从x1到x2的平均变化率
# 实际上表示的是A(x1,y,)点,B(x2,y2)点之间线段的斜率 KAB = (f(x2)-f(x1))/(x2-x1)
# 函数y=f(x)在点(x0,y0)处的切线方程为y-y0=f~(x0)(x-x0)     # 就是斜率k的值

f = lambda x: (x - 4.3) ** 2 + 7.5 * x + 6  # 有平方,开口向上的,f是一个函数
g = lambda x: 2 * x - 1.1  # f的导数
# x = np.linspace(-5, 9, 14)
# plt.plot(x, f(x), marker="o", )
# plt.show()

# 设起始值的数值
v_min = np.random.randint(-10, 10, size=1)[0]
# 该值记录梯度下降过程中,上一步的值
v_min_last = v_min + 1
# 什么时候梯度下降结束,也就是精度的退出条件
precision = 0.0001
# 步幅
step = 0.01
# 再定一个退出条件,循环次数
max_time = 3000

count = 0
print("随机生成的最小值:--------------------------", v_min)
while True:
    if np.abs(v_min - v_min_last) < precision:
        break
    if count > max_time:
        break
    v_min_last = v_min
    #               把v_min最小值带入g导函数,乘以步幅
    v_min = v_min - g(v_min) * step
    print("-----------------------------梯度下降更新的最小值", v_min)
    count += 1

第二部分

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# 梯度下降求解w和b
X = np.linspace(2.5, 12, 25)
w = np.random.randint(2, 10, size=1)[0]
b = np.random.randint(-5, 5, size=1)[0]
y = X * w + b + np.random.randn(25) * 2

# plt.scatter(X, y)
# plt.show()
lr = LinearRegression(fit_intercept=True)
# X数据必须是二维的
lr.fit(X.reshape(-1, 1), y)
# 未知数w_
w_ = lr.coef_
# 截距b_
b_ = lr.intercept_


# print(X, "\n", w, "\n", b, "\n")
# print(w_, b_)     # np.random.randn(25) * 2因为这个抖动,使得数据不一致
# 如果要求解斜率,LinearRegression使用的也是梯度下降

# 求解斜率和截距
class Linear_model(object):
    def __init__(self):
        self.w = np.random.randn(1)[0]
        self.b = np.random.randn(1)[0]
        print(f"------------------------起始的斜率{self.w},起始的截距{self.b}")

    # model就是方程f(x) = wx + b
    def model(self, x):
        return self.w * x + self.b

    # 定义损失函数,只要是线性问题,原理都是最小二乘法
    def loss(self, x, y):
        cost = (y - self.model(x)) ** 2

        # 求偏导数,把其他的都当成已知数,求一个未知数的导数
        # 导数是偏导数的一种特殊形式
        g_w = 2 * (y - self.model(x)) * (-x)
        g_b = 2 * (y - self.model(x)) * (-1)
        return g_w, g_b

    # 梯度下降
    def gradient_descend(self, g_w, g_b, step=0.01):
        self.w = self.w - g_w * step
        self.b = self.b - g_b * step
        print(f"------------------------当前的斜率{self.w},起始的截距{self.b}")

    def fit(self, X, y):
        w_last = self.w + 1
        b_last = self.b + 1
        precision = 0.00001
        max_count = 3000
        count = 0
        while True:
            if (np.abs(self.w - w_last) < precision) and (np.abs(self.b - b_last), precision):
                break
            if count > max_count:
                break
            # 更新斜率和截距
            g_w = 0
            g_b = 0
            size = X.shape[0]
            for i, j in zip(X, y):
                g_w += self.loss(i, j)[0] / size
                g_b += self.loss(i, j)[1] / size
            self.gradient_descend(g_w, g_b)
            count += 1

    def coef_(self):
        return self.w

    def intercepe(self):
        return self.b


lm = Linear_model()

发布了30 篇原创文章 · 获赞 5 · 访问量 3316

猜你喜欢

转载自blog.csdn.net/Python_DJ/article/details/104448947
今日推荐