机器学习:多项式回归(Python)

news2024/11/16 17:39:46

多元线性回归闭式解:

closed_form_sol.py

import numpy as np
import matplotlib.pyplot as plt


class LRClosedFormSol:
    def __init__(self, fit_intercept=True, normalize=True):
        """
        :param fit_intercept: 是否训练bias
        :param normalize: 是否标准化数据
        """
        self.theta = None  # 训练权重系数
        self.fit_intercept = fit_intercept  # 线性模型的常数项。也即偏置bias,模型中的theta0
        self.normalize = normalize  # 是否标准化数据
        if normalize:
            self.feature_mean, self.feature_std = None, None  # 特征的均值,标准方差
        self.mse = np.infty  # 训练样本的均方误差
        self.r2, self.r2_adj = 0.0, 0.0  # 判定系数和修正判定系数
        self.n_samples, self.n_features = 0, 0  # 样本量和特征数

    def fit(self, x_train, y_train):
        """
        模型训练,根据是否标准化与是否拟合偏置项分类讨论
        :param x_train: 训练样本集
        :param y_train: 训练目标集
        :return:
        """
        if self.normalize:
            self.feature_mean = np.mean(x_train, axis=0)  # 按样本属性计算样本均值
            self.feature_std = np.std(x_train, axis=0) + 1e-8  # 样本方差,为避免零除,添加噪声
            x_train = (x_train - self.feature_mean) / self.feature_std  # 标准化
        if self.fit_intercept:
            x_train = np.c_[x_train, np.ones_like(y_train)]  # 添加一列1,即偏置项样本
        # 训练模型
        self._fit_closed_form_solution(x_train, y_train)  # 求闭式解

    def _fit_closed_form_solution(self, x_train, y_train):
        """
        线性回归的闭式解,单独函数,以便后期扩充维护
        :param x_train: 训练样本集
        :param y_train: 训练目标集
        :return:
        """
        # pinv伪逆,即(A^T * A)^(-1) * A^T
        self.theta = np.linalg.pinv(x_train).dot(y_train)  # 非正则化
        # xtx = np.dot(x_train.T, x_train) + 0.01 * np.eye(x_train.shape[1])  # 按公式书写
        # self.theta = np.dot(np.linalg.inv(xtx), x_train.T).dot(y_train)

    def get_params(self):
        """
        返回线性模型训练的系数
        :return:
        """
        if self.fit_intercept:  # 存在偏置项
            weight, bias = self.theta[:-1], self.theta[-1]
        else:
            weight, bias = self.theta, np.array([0])
        if self.normalize:  # 标准化后的系数
            weight = weight / self.feature_std.reshape(-1, 1)  # 还原模型系数
            bias = bias - weight.T.dot(self.feature_mean)
        return weight, bias

    def predict(self, x_test):
        """
        测试数据预测,x_test:待预测样本集,不包括偏置项1
        :param x_test:
        :return:
        """
        try:
            self.n_samples, self.n_features = x_test.shape[0], x_test.shape[1]
        except IndexError:
            self.n_samples, self.n_features = x_test.shape[0], 1  # 测试样本数和特征数
        if self.normalize:
            x_test = (x_test - self.feature_mean) / self.feature_std  # 测试数据标准化
        if self.fit_intercept:
            x_test = np.c_[x_test, np.ones(shape=x_test.shape[0])]  # 存在偏置项,添加一列1
        return x_test.dot(self.theta)

    def cal_mse_r2(self, y_pred, y_test):
        """
        计算均方误差,计算拟合优度的判定系数R方和修正判定系数
        :param y_pred: 模型预测目标真值
        :param y_test: 测试目标真值
        :return:
        """
        self.mse = ((y_test - y_pred) ** 2).mean()  # 均方误差
        # 计算测试样本的判定系数和修正判定系数
        self.r2 = 1 - ((y_test - y_pred) ** 2).sum() / ((y_test - y_test.mean()) ** 2).sum()
        self.r2_adj = 1 - (1 - self.r2) * (self.n_samples - 1) / (self.n_samples - self.n_features - 1)
        return self.mse, self.r2, self.r2_adj

    def plt_predict(self, y_pred, y_test, is_show=True, is_sort=True):
        """
        绘制预测值与真实值对比图
        :return:
        """
        if self.mse is np.infty:
            self.cal_mse_r2(y_pred, y_test)
        if is_show:
            plt.figure(figsize=(7, 5))
        if is_sort:
            idx = np.argsort(y_test)
            plt.plot(y_pred[idx], "r:", lw=1.5, label="Predictive Val")
            plt.plot(y_test[idx], "k--", lw=1.5, label="Test True Val")
        else:
            plt.plot(y_pred, "r:", lw=1.5, label="Predictive Val")
            plt.plot(y_test, "k--", lw=1.5, label="Test True Val")
        plt.xlabel("Test sample observation serial number", fontdict={"fontsize": 12})
        plt.ylabel("Predicted sample value", fontdict={"fontsize": 12})
        plt.title("The predictive values of test samples \n MSE = %.5e, R2 = %.5f, R2_adj = %.5f"
                  % (self.mse, self.r2, self.r2_adj), fontdict={"fontsize": 14})
        plt.legend(frameon=False)
        plt.grid(ls=":")
        if is_show:
            plt.show()

多项式构造

polynomial_feature.py

import numpy as np

class PolynomialFeatureData:
    """
    生成特征多项式数据
    """
    def __init__(self, x, degree, with_bias=False):
        """
        参数初始化
        :param x: 采用数据,向量形式
        :param degree: 多项式最高阶次
        :param with_bias: 是否需要偏置项
        """
        self.x = np.asarray(x)
        self.degree = degree
        self.with_bias = with_bias
        if with_bias:
            self.data = np.zeros((len(x), degree + 1))
        else:
            self.data = np.zeros((len(x), degree))

    def fit_transform(self):
        """
        构造多项式特征数据
        :return:
        """
        if self.with_bias:
            self.data[:, 0] = np.ones(len(self.x))
            self.data[:, 1] = self.x.reshape(-1)
            for i in range(2, self.degree + 1):
                self.data[:, i] = (self.x ** i).reshape(-1)
        else:
            self.data[:, 0] = self.x.reshape(-1)
            for i in range(1, self.degree):
                self.data[:, i] = (self.x ** (i + 1)).reshape(-1)

        return self.data


if __name__ == '__main__':
    x = np.random.randn(5)
    feat_obj = PolynomialFeatureData(x, 5, with_bias=True)
    data = feat_obj.fit_transform()
    print(data)

 多项式回归

test_polynomial_fit.py

import numpy as np
import matplotlib.pyplot as plt
from polynomial_feature import PolynomialFeatureData
from closed_form_sol import LRClosedFormSol


def objective_fun(x):
    """
    目标函数,假设一个随机二次多项式
    :param x: 采样数据,向量
    :return:
    """
    return 0.5 * x ** 2 + x + 2

np.random.seed(42)  # 随机种子,以便结果可再现
n = 30  # 样本量
raw_x = np.sort(6 * np.random.rand(n, 1) - 3)  # 采样数据[-3, 3],均匀分布
raw_y = objective_fun(raw_x) + 0.5 * np.random.randn(n, 1)  # 目标值,添加噪声

degree = [1, 2, 5, 10, 15, 20]  # 拟合多项式的最高阶次
plt.figure(figsize=(15, 8))
for i, d in enumerate(degree):
    feature_obj = PolynomialFeatureData(raw_x, d, with_bias=False)  # 特征数据对象
    X_samples = feature_obj.fit_transform()  # 生成特征多项式数据

    lr_cfs = LRClosedFormSol()  # 采用线性回归求解多项式回归
    lr_cfs.fit(X_samples, raw_y)  # 求解多项式回归系数
    theta = lr_cfs.get_params()  # 获得系数
    print("degree: %d, theta is " %d, theta[0].reshape(-1)[::-1], theta[1])
    y_train_pred = lr_cfs.predict(X_samples)  # 在训练集上的预测

    # 测试样本采样
    X_test_raw = np.linspace(-3, 3, 150)  # 测试数据
    y_test = objective_fun(X_test_raw)  # 测试数据的真值
    feature_obj = PolynomialFeatureData(X_test_raw, d, with_bias=False)  # 特征数据对象
    X_test = feature_obj.fit_transform()  # 生成特征多项式数据
    y_test_pred = lr_cfs.predict(X_test)  # 模型在测试样本上的预测值

    # 可视化不同阶次下的多项式拟合曲线
    plt.subplot(231 + i)
    plt.scatter(raw_x, raw_y, edgecolors="k", s=15, label="Raw Data")
    plt.plot(X_test_raw, y_test, "k-", lw=1, label="Objective Fun")
    plt.plot(X_test_raw, y_test_pred, "r--", lw=1.5, label="Polynomial Fit")
    plt.legend(frameon=False)
    plt.grid(ls=":")
    plt.xlabel("$x$", fontdict={"fontsize": 12})
    plt.ylabel("$y(x)$", fontdict={"fontsize": 12})
    test_ess = (y_test_pred.reshape(-1) - y_test) ** 2  # 误差平方
    test_mse, test_std = np.mean(test_ess), np.std(test_ess)
    train_ess = (y_train_pred - raw_y) ** 2  # 误差平方
    train_mse, train_std = np.mean(train_ess), np.std(train_ess)
    plt.title("Degree {} Test Mse = {:.2e}(+/-{:.2e}) \n Train Mse = {:.2e}(+/-{:.2e})"
              .format(d, test_mse, test_std, train_mse, train_std))
    plt.axis([-3, 3, 0, 9])
plt.tight_layout()
plt.show()

输出结果:

学习曲线

learning_curve1.py

import numpy as np
import matplotlib.pyplot as plt
from polynomial_feature import PolynomialFeatureData
from closed_form_sol import LRClosedFormSol
from sklearn.model_selection import train_test_split


def objective_fun(x):
    """
    目标函数,假设一个随机二次多项式
    :param x: 采样数据,向量
    :return:
    """
    return 0.5 * x ** 2 + x + 2


np.random.seed(42)  # 随机种子,以便结果可再现
n = 100  # 样本量
raw_x = np.sort(6 * np.random.rand(n, 1) - 3)  # 采样数据[-3, 3],均匀分布
raw_y = objective_fun(raw_x) + 0.5 * np.random.randn(n, 1)  # 目标值,添加噪声

degree = [1, 2, 5, 10]  # 拟合阶次
plt.figure(figsize=(10, 7))  # 图像尺寸
for i, d in enumerate(degree):
    # 生成特征多项式对象,包含偏置项
    feta_obj = PolynomialFeatureData(raw_x, d, with_bias=False)
    X_sample = feta_obj.fit_transform()  # 生成特征多项式数据
    X_train, X_test, y_train, y_test = \
        train_test_split(X_sample, raw_y, test_size=0.2, random_state=0)
    train_mse, test_mse = [], []  # 随样本量的增加,训练误差和测试误差
    for j in range(1, 80):
        lr_cfs = LRClosedFormSol()  # 线性回归闭式解
        theta = lr_cfs.fit(X_train[:j, :], y_train[:j])  # 拟合多项式
        y_test_pred = lr_cfs.predict(X_test)  # 测试样本预测
        y_train_pred = lr_cfs.predict(X_train[:j, :])  # 训练样本预测
        train_mse.append(np.mean((y_train_pred.reshape(-1) - y_train[:j].reshape(-1)) ** 2))
        test_mse.append(np.mean((y_test_pred.reshape(-1) - y_test.reshape(-1)) ** 2))

    # 可视化多项式拟合曲线
    plt.subplot(221 + i)
    plt.plot(train_mse, "k-", lw=1, label="Train")
    plt.plot(test_mse, "r--", lw=1.5, label="Test")
    plt.legend(frameon=False)
    plt.grid(ls=":")
    plt.xlabel("Train Size", fontdict={"fontsize": 12})
    plt.ylabel("MSE", fontdict={"fontsize": 12})
    plt.title("Learning Curve by Degree {}".format(d))
    if i == 0:
        plt.axis([0, 80, 0, 4])
    if i == 1:
        plt.axis([0, 80, 0, 1])
    if i in [2, 3]:
        plt.axis([0, 80, 0, 2])
plt.tight_layout()
plt.show()

 

学习曲线(采用10折交叉验证)

learning_curve2.py

import numpy as np
import matplotlib.pyplot as plt
from polynomial_feature import PolynomialFeatureData
from closed_form_sol import LRClosedFormSol
from sklearn.model_selection import KFold


def objective_fun(x):
    """
    目标函数,假设一个随机二次多项式
    :param x: 采样数据,向量
    :return:
    """
    return 0.5 * x ** 2 + x + 2


np.random.seed(42)  # 随机种子,以便结果可再现
n = 300  # 样本量
raw_x = np.sort(6 * np.random.rand(n, 1) - 3)  # 采样数据[-3, 3],均匀分布
raw_y = objective_fun(raw_x) + 0.5 * np.random.randn(n, 1)  # 目标值,添加噪声

k_fold = KFold(n_splits=10)  # 划分为10折
degree = [1, 2, 4, 6, 8, 10]  # 拟合阶次
plt.figure(figsize=(15, 8))  # 图像尺寸
for i, d in enumerate(degree):
    # 生成特征多项式对象,包含偏置项
    feta_obj = PolynomialFeatureData(raw_x, d, with_bias=False)
    X_sample = feta_obj.fit_transform()  # 生成特征多项式数据
    train_mse, test_mse = [], []  # 随样本量的增加,训练误差和测试误差
    for j in range(1, 270):
        train_mse_, test_mse_ = 0.0, 0.0  # 交叉验证
        for idx_train, idx_test in k_fold.split(raw_x, raw_y):
            X_train, y_train = X_sample[idx_train], raw_y[idx_train]
            X_test, y_test = X_sample[idx_test], raw_y[idx_test]
            lr_cfs = LRClosedFormSol()  # 线性回归闭式解
            theta = lr_cfs.fit(X_train[:j, :], y_train[:j])  # 拟合多项式
            y_test_pred = lr_cfs.predict(X_test)  # 测试样本预测
            y_train_pred = lr_cfs.predict(X_train[:j, :])  # 训练样本预测
            train_mse_ += np.mean((y_train_pred.reshape(-1) - y_train[:j].reshape(-1)) ** 2)
            test_mse_ += np.mean((y_test_pred.reshape(-1) - y_test.reshape(-1)) ** 2)
        train_mse.append(train_mse_ / 10)
        test_mse.append(test_mse_ / 10)

    # 可视化多项式拟合曲线
    plt.subplot(231 + i)
    plt.plot(train_mse, "k-", lw=1, label="Train")
    plt.plot(test_mse, "r--", lw=1.5, label="Test")
    plt.legend(frameon=False)
    plt.grid(ls=":")
    plt.xlabel("Train Size", fontdict={"fontsize": 12})
    plt.ylabel("MSE", fontdict={"fontsize": 12})
    plt.title("Learning Curve by Degree {}".format(d))
    if i == 0:
        plt.axis([0, 250, 0, 4])
    else:
        plt.axis([0, 250, 0, 1])
plt.tight_layout()
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重写Sylar基于协程的服务器(1、日志模块的架构)

重写Sylar基于协程的服务器(1、日志模块的架构) 重写Sylar基于协程的服务器系列: 重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar) 重写Sylar基于协程的服务器(1、日志模…

2.室内设计学习 - CAD 2021 调整经典界面教程及基本设置

设置经典界面 1.在第二行的空白处右击,弹出对话框,并点击【关闭】,关闭掉。 2.菜单栏没有显示的情况下,在最上面的一排,点击向下的箭头展开下拉框,勾选 【显示菜单栏】 3.点击菜单【工具】-【工具栏】-【a…

AES 加解密python实现

1. 要求 编程实现AES-128的加解密算法,满足给定明文和密钥加密得到密文,给定密文和密钥解密得到明文,最终用界面化的形式呈现。 2. 算法流程 程序主要分为加密与解密两个大模块。在加密模块中包括四个小模块,分别为轮密钥加、字…

C语言KR圣经笔记 6.4结构体指针 6.5自引用结构体

6.4 结构体指针 为了说明结构体指针和数组的某些注意事项&#xff0c;我们把上一节的关键字计数程序再写一次&#xff0c;不过这回使用指针而不是数组下标。 keytab 的外部声明不需要动&#xff0c;但 main 和 binsearch 确实需要修改。 #include <stdio.h> #include …

3、css设置样式总结、节点、节点之间关系、创建元素的方式、BOM

一、css设置样式的方式总结&#xff1a; 对象.style.css属性 对象.className ‘’ 会覆盖原来的类 对象.setAttribut(‘style’,‘css样式’) 对象.setAttribute(‘class’,‘类名’) 对象.style.setProperty(css属性名,css属性值) 对象.style.cssText “css样式表” …

开发工具之GIT协同开发流程和微服务部署实践与总结

GIT协同开发流程和微服务部署的实践&#xff0c;并总结经验和教训。通过合理的GIT协同开发流程和良好的微服务部署策略&#xff0c;团队可以更高效地开发和部署软件。 ## 引言 在当今快节奏的软件开发环境中&#xff0c;采用合适的工具和流程对于实现高效协同开发和可靠部署至…

1.25时间序列分析,FB先知模型、简要傅里叶变化解决周期性变化,实例步骤

目录 FB概念 ​编辑 GEOGEBRA可视化傅里叶​编辑 先知模型步骤 财务数据要考虑到可解释性 FB模型概念 可以用傅里叶级数来描述周期性变化的因素 GEOGEBRA可视化傅里叶 先知模型步骤

vue+ElementPlus实现中国省市区三级级联动封装

安装插件获取中国省份的所有数据 npm install element-china-area-data -S 借助ElementPlus 级联选择器 Cascader实现 <template><div><el-cascadersize"large":options"options"v-model"selectedOptions"change"handleCh…

C# 一个快速读取写入操作execl的方法封装

这里封装了3个实用类ExcelDataReaderExtensions&#xff0c;ExcelDataSetConfiguration&#xff0c;ExcelDataTableConfiguration和一个实用代码参考&#xff1a; using ExcelDataReader; using System; using System.Collections.Generic; using System.Linq; using System.T…

2024.1.29 关于 Redis 缓存详解

目录 缓存基本概念 二八定律 Redis 作为缓存 缓存更新策略 定期生成 实时生成 内存淘汰策略 缓存使用的注意事项 关于缓存预热 关于缓存穿透 关于缓存雪崩 关于缓存击穿&#xff08;瘫痪&#xff09; 缓存基本概念 所谓缓存&#xff0c;其实就是将一部分常用数据放…

向日葵企业“云策略”升级 支持Android 被控策略设置

此前&#xff0c;贝锐向日葵推出了适配PC企业客户端的云策略功能&#xff0c;这一功能支持管理平台统一修改设备设置&#xff0c;上万设备实时下发实时生效&#xff0c;很好的解决了当远程控制方案部署后&#xff0c;想要灵活调整配置需要逐台手工操作的痛点&#xff0c;大幅提…

计算机网络-数据交换方式(电路交换 报文交换 分组交换及其两种方式 )

文章目录 为什么要数据交换&#xff1f;总览电路交换电路交换的各个阶段建立连接数据传输释放连接 电路交换的特点电路交换的优缺点 报文交换报文交换流程报文交换的优缺点 分组交换分组交换流程分组交换的优缺点 数据交换方式的选择分组交换的两种方式数据报方式数据报方式的特…

正则表达式(RE)

什么是正则表达式 正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;。正则表达式通常被用来检索、替换那些符合某个规则的文本 正则表达式的作用 验证数据的有效性替换文本内容从字符串中提取子字符串 匹配单个字符 字符功能.匹配任意1个…

(一)Spring 核心之控制反转(IoC)—— 配置及使用

目录 一. 前言 二. IoC 基础 2.1. IoC 是什么 2.2. IoC 能做什么 2.3. IoC 和 DI 是什么关系 三. IoC 配置的三种方式 3.1. XML 配置 3.2. Java 配置 3.3. 注解配置 四. 依赖注入的三种方式 4.1. 属性注入&#xff08;setter 注入&#xff09; 4.2. 构造方法注入&a…

ES Serverless让日志检索更加便捷

前言 在项目中,或者开发过程中,出现bug或者其他线上问题,开发人员可以通过查看日志记录来定位问题。通过日志定位 bug 是一种常见的软件开发和运维技巧,只有观察日志才能追踪到具体代码。在软件开发过程中,开发人员会在代码中添加日志记录,以记录程序的运行情况和异常信…

【蓝桥杯日记】复盘篇二:分支结构

前言 本篇笔记主要进行复盘的内容是分支结构&#xff0c;通过学习分支结构从而更好巩固之前所学的内容。 目录 前言 目录 &#x1f34a;1.数的性质 分析&#xff1a; 知识点&#xff1a; &#x1f345;2.闰年判断 说明/提示 分析&#xff1a; 知识点&#xff1a; &am…

【Linux操作系统】:Linux开发工具编辑器vim

目录 Linux 软件包管理器 yum 什么是软件包 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux 开发工具 Linux编辑器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 插入模式 插入模式切换为命令模式 移动光标 删除文字 复制 替换 撤销 跳至指…

C++——list的使用及其模拟实现

list 文章目录 list1. 基本使用1.1 list对象的定义1.2 增&#xff08;插入数据&#xff09;1.3 删&#xff08;删除数据&#xff09;1.4 遍历访问 2. 模拟实现2.1 节点类ListNode2.2 封装ListNode类&#xff0c;实现list基本功能2.3 实现迭代器iterator2.3.1 实现const迭代器co…

使用Hutool工具包解析、生成XML文件

说明&#xff1a;当我们在工作中需要将数据转为XML文件、或者读取解析XML文件时&#xff0c;使用Hutool工具包中的XMLUtil相关方法是最容易上手的方法&#xff0c;本文介绍如何使用Hutool工具包来解析、生成XML文件。 开始之前&#xff0c;需要导入Hutool工具包的依赖 <de…

力扣hot100 柱状图中最大的矩形 单调栈

Problem: 84. 柱状图中最大的矩形 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考地址 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public static int largestRectangleArea(int[] height){Stack&l…