机器学习之线性回归
广义线性模型
1.定义
目标值 y 是输入变量 x 的线性组合。 数学概念表示为:如果 y
是预测值,那么有:y(w,x) = w0+w1x1+w2x2+...wnxn
在整个模块中,我们定义向量 w = (w0,w1,...wn) 作为 coef_ ,定义 w0 作为 intercept_
作为 coef_ ,定义 作为 intercept_ 。
2.理论依据:
(1)拟合:(找函数)
科学和工程问题可以通过诸如采样、实验等方法获得若干离散的数据,根据这些数据,我们往往希望得到一个连续的函数(也就是曲线)或者更加密集的离散方程与已知数据相吻合,这过程就叫做拟合(fitting)。
(2)插值:(找值满足条件的函数)
给定 n个离散数据点(称为节点)(xi,yi) i=1,2,...n,对于x(x != xi,i=1,2...n),求 x所对应的 y的值称为内插.
f(x)为定义在区间 [a,b]上的函数。x1,x2...xn为[a,b]上n个互不相同的点, G为给定的某一函数类。若G上有函数 g(x)满足:g(xi) = f(xi),k = 1,2,....,n则称g(x)为f(x)关于节点在 G上的插值函数。
(3)最小二乘法:
最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。
(4)奇异性:
从数学角度来说,所谓奇异性就是指函数的不连续或导数不存在,表现出奇异性的点称为奇异点...
3.总结
我们在实际生产生活或是实验中获得了一些数据,例如(x,y)这样的二元组,当我们想知道这些数据之间的联系时,找到它的数学表达式就是一种不错的方法。此时,你可能会想到用 ‘拟合’ 的方式去找到它的数学表达式,想要拟合,就离不开插值。
我们在现实生活中得到的数据,不可能总是完美的找到一条曲线,恰好可以将获得的数据拟合,所以在拟合的过程中会产生一些误差,所谓的误差,就是实际数据值与预测数据值之间的差。我们总是希望找到一条曲线,该条曲线可以最大程度的代替我们得到的数据。换句话说,如果我们找到一条曲线,它的预测值与实际值的差的平方和最小,那么该条曲线不就可以最大程度的代替我们得到的数据吗?所以此时问题就转化到了求预测值与实际值的差的平方和最小上面来了,这就是最小二乘法!在最小二乘法求解时,会用到求导。为什么要用求导的方式?
点动成线,线动成面,在立体空间中,一个曲面是由很多条曲线组成的,你如果想要找该曲面的最值,就相当于找这个曲面的最高点或最低点。如果你沿着这个面的某一条线的切线走,它不就可以以最快的速度到达最值点(最高点或最低点),这就是为什么要求导数,而且求导还可以起到降维的效果(平方求导就会变成一次方),简化运算,
3.应用场景
线性回归模型常用来预测连续性目标值(分类的目标变量是离散型数据)的数值,
4.代码实现
sklearn 中的线性回归模型有以下参数:
fit(X,y),训练,拟合参数
predict(X),预测
score(X,y), 得到评分结果
coef_,存放回归系数
intercept_,存放截距
(1)简单的函数回归分析
以下是代码:
import random
#调用 sklearn 中的线性模型
from sklearn import linear_model
reg = linear_model.LinearRegression()
def generate(x):
#在数据较少时增加随机数扰动(random.random()),可以更好的使模型泛化。
y = 2*x+10+random.random()
return y
train_x = []
train_y = []
for x in range(1000):
train_x.append([x])
y = generate(x)
train_y.append([y])
#使用 fit 函数进行模型训练
reg.fit (train_x, train_y)
# coef_ 保存线性模型的系数w
print(reg.coef_)
print(reg.intercept_)
(2)糖尿病回归分析
数据集Diabetes,包含442个患者的10个生理特征(年龄,性别、体重、血压)和一年以后疾病级数指标。
10项特征:
年龄,性别,体质指数,血压 以及 s1,s2,s3,s4,s4,s6 (六种血清的化验数据)
"""
使用sklearn自带的糖尿病数据集,进行回归分析
Diabetes:包含442个患者的10个生理特征(年龄,性别、体重、血压)(x)和一年以后疾病级数指标(y)
"""
以下是代码:
from sklearn import datasets
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import pandas as pd
# 加载数据
diabetes = datasets.load_diabetes()
data = diabetes.data
# print(pd.DataFrame(data).head())
# 数据探索
# print(data.shape)
# print(data)
# 训练集 70%,测试集30%
train_x, test_x, train_y, test_y = train_test_split(diabetes.data, diabetes.target, test_size=0.3, random_state=14)
# print(len(train_x))
#回归训练及预测
clf = linear_model.LinearRegression()
clf.fit(train_x, train_y)
#该模型的系数是一个10行一列的 np 数组
print(clf.coef_)
#print(train_x.shape)
#print(clf.score(test_x, test_y))
#给出一个人的 10 项指标(x),预测一年以后的病情(y)
pred_y = clf.predict(test_x)
print(mean_squared_error(test_y, pred_y))
(3)股票回归分析
pandas 专门提供了从财经网站上获得数据的接口,我们需要使用时,只需使用 pip 命令安装pandas_datareader 接口就可以了。
命令:pip install pandas_datareader
以下是代码:
import statsmodels.api as sm
import statsmodels.formula.api as smf
import statsmodels.graphics.api as smg
import patsy
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
from scipy import stats
import seaborn as sns
import datetime, os, warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #可以显示负号
# 设置起始时间
start = datetime.datetime(2019,1,1)
end = datetime.datetime(2019,12,31)
from pandas_datareader.data import DataReader
# 读取上证综指 及 探路者数据
def load_data():
if os.path.exists('000001.csv'):
data_ss = pd.read_csv('000001.csv')
data_tlz = pd.read_csv('300005.csv')
else:
# 上证综指
data_ss = DataReader("000001.SS", "yahoo",start,end)
# 300005 探路者股票 深证
data_tlz = DataReader("300005.SZ", "yahoo",start,end)
data_ss.to_csv('000001.csv')
data_tlz.to_csv('300005.csv')
return data_ss, data_tlz
data_ss, data_tlz = load_data()
# 探路者与上证综指
close_ss = data_ss["Close"]
close_tlz = data_tlz["Close"]
# 将探路者与上证综指进行数据合并
stock = pd.merge(data_ss, data_tlz, left_index = True, right_index = True)
# print(stock.head())
stock = stock[["Close_x","Close_y"]]
stock.columns = ["上证综指","探路者"]
# 统计每日收益率
daily_return = (stock.diff()/stock.shift(periods = 1)).dropna()
print(daily_return.head())
# 找出当天收益率大于10%的,应该是没有,因为涨停为10%
print(daily_return[daily_return["探路者"] > 0.1])
# 每日收益率可视化
fig,ax = plt.subplots(nrows=1,ncols=2,figsize=(15,6))
daily_return["上证综指"].plot(ax=ax[0])
ax[0].set_title("上证综指")
daily_return["探路者"].plot(ax=ax[1])
ax[1].set_title("探路者")
plt.show()
# 散点图
fig,ax = plt.subplots(nrows=1,ncols=1,figsize=(12,6))
plt.scatter(daily_return["探路者"],daily_return["上证综指"])
plt.title("每日收益率散点图 from 探路者 & 上证综指")
plt.show()
# 回归分析
#statsmodels 中有现成的 OLS 线性回归模型,直接调用就能用😆,而且还有 summary() 函数直接查看训练结果!!!太好用了
import statsmodels.api as sm
# 加入截距项
daily_return["intercept"]=1.0
model = sm.OLS(daily_return["探路者"],daily_return[["上证综指","intercept"]])
results = model.fit()
print(results.summary())