【线性回归】sklearn进行简单的多项式线性回归以及求导函数

2021.12.31补充
sklearn中有现成的多项式回归,并不需要自己实现

需求分析

处理一段数据,需要求某点切线的斜率。想法是先用线性回归拟合出曲线的解析式,然后根据高中学的导数的定义求出某点的导数。

数据很整齐,但是是一条曲线,应该先把x进行升维然后进行更高次的线性回归,输出曲线解析式。然后根据导函数的定义输出导函数解析式。但是因为我没学过高等数学也没学过线性代数,sklearn也只会熟悉最基础的几个部分所以代码有不太成熟的地方就当是抛砖引玉。

关键代码

升维部分

初高中学过的 y = k x + b y = kx+b y=kx+b图像时一条直线,实际数据很少会这么规整,所以要进行升维
(以三次多项式为例) y y y= k 1 k_1 k1 x 3 x^3 x3+ k 2 k_2 k2 x 2 x^2 x2+ k 3 k_3 k3 x x x+ b b b的形式
学过线代的就可以写成 y = w x + b y=wx+b y=wx+b
像我这样没学过的,就先百度明白了再接着写吧

def __rise_x_dimension(self, x_data):
        """
        多项式升维
        :param n: 升维次数,默认四次
        """
        res = []
        temp_x_data = x_data.reshape(-1, 1)
        for i in range(1, self.dimension + 1):
            res.append(temp_x_data ** i)
        return np.hstack(res)

求导部分

就是根据导数的定义了,没啥好说的。感觉有更好的办法,发现了再说。

def __get_k_s(self, point_x):
        """
        获取切线方程
        :param point_x:切点坐标
        """
        for i in range(0, self.dimension):
            self.k += (i + 1) * (point_x ** i) * self.w[i]
        temp_x = self.__rise_x_dimension(np.array([point_x]).reshape(1, 1))
        self.s = np.dot(temp_x, self.w) + self.b - self.k * point_x

全部代码

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

# 处理数据相关的代码,和整体没啥关系
def y_filter(raw):
    res = raw[raw.iloc[:, 1] < 5e-7]
    return res


class TangentSlope:
    def __init__(self, x_data, y_data, dimension=4):
        # 原始数据
        self.x_raw_data = x_data
        self.y_raw_data = y_data
        # 用于训练的数据
        self.x_data = None
        # 多项式次数
        self.dimension = dimension
        # 拟合曲线解析式参数
        self.w = None
        self.b = None
        # 拟合曲线的y值
        self.y_hat = None
        # 切线解析式参数(斜率、截距)
        self.k = 0
        self.s = 0
        # 回归模型
        self.line_regression = LinearRegression()

    def __rise_x_dimension(self, x_data):
        """
        多项式升维
        :param n: 升维次数,默认四次
        """
        res = []
        temp_x_data = x_data.reshape(-1, 1)
        for i in range(1, self.dimension + 1):
            res.append(temp_x_data ** i)
        return np.hstack(res)

    def __get_k_s(self, point_x):
        """
        获取切线方程
        :param point_x:切点坐标
        """
        for i in range(0, self.dimension):
            self.k += (i + 1) * (point_x ** i) * self.w[i]
        temp_x = self.__rise_x_dimension(np.array([point_x]).reshape(1, 1))
        self.s = np.dot(temp_x, self.w) + self.b - self.k * point_x

    def fit(self, show_hat=False, show_raw=False):
        self.x_data = self.__rise_x_dimension(self.x_raw_data)
        self.line_regression.fit(X=self.x_data, y=self.y_raw_data)
        self.w = np.array(self.line_regression.coef_).reshape(-1, 1)
        self.b = self.line_regression.intercept_
        self.y_hat = np.dot(self.x_data, self.w) + self.b

        if show_hat:
            plt.plot(self.x_raw_data, self.y_hat, color='r')
        if show_raw:
            plt.scatter(self.x_raw_data, self.y_raw_data, color='b')
        if show_hat or show_raw:
            plt.show()

    def get_tangent(self, point_x, show_chart=True):
        """
        获取切线
        :param show_chart: 是否显示图表
        :param point_x:切点x坐标
        :return:
        """
        self.__get_k_s(point_x)
        print("切线斜率", self.k)
        if show_chart:
            plt.plot(self.x_raw_data, self.y_raw_data, color='b')
            tangent_y = self.k * self.x_raw_data + self.s
            tangent_y = tangent_y.reshape(-1, 1)
            plt.plot(self.x_raw_data, tangent_y, color="r")
            plt.show()


if __name__ == '__main__':
	
	#获取数据的x,y根据自己的实际业务
    #PATH = "../data/idvg_comp.csv"
    #raw_data = pd.read_csv(PATH)
    #data_1 = y_filter(raw_data[["x1", "y1"]])
    #x = np.log10(data_1["y1"].values)
    #y = data_1["x1"].values

    tangent_slope = TangentSlope(x, y, 2)
    tangent_slope.fit(False, True)
    tangent_slope.get_tangent(-7)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值