本文所用文件的百度云链接:
链接:https://pan.baidu.com/s/15-qbrbtRs4frup24Y1i5og
提取码:pm2c
线性拟合和线性预测,两字之差,究竟有哪些区别呢,我个人认为首先这两个的应用场景不一样,其次得到的结果表现的内容不一样,然后就是计算过程不同。
线性拟合
线性拟合可以寻求与一组数据走向趋势规律相适应的线性表达式方程,通俗来讲,就是用一条直线来描述数据变换的规律,直线的方程就是y=kx+b,结果相对简单,表现形式简单粗暴,优点是一目了然,缺点就是只能大概的给出规律,并不能将数据变换的规律完全体现,并且不是所有的数据都可以由线性来表示的,这个就要后面再说了,后面就会涉及到分类聚类等等。
有一组股价:
[x1, y1]
[x2, y2]
[x3, y3]
...
[xn, yn]
根据y = kx+b:
y1 = kx1 + b
y2 = kx2 + b
y3 = kx3 + b
....
yn = kxn + b
使用np.linalg.lstsq(A, B) 求得的x与b, 可能无法让所有的方程成立, 但是拟合的直线方程的误差是最小的.
案例: 利用线性拟合画出股价的趋势线.
趋势线: (最高价+最低价+收盘价) / 3
线性拟合 lstsq(A, B)
这里重点说一下拟合的这部分代码,很简单,A是一个30 * 2的矩阵,两列分别表示k和1,即x的系数和b的系数,B输出结果的单列矩阵,即y的值,然后就形成了一个解k和b的方程组,利用lstsq方法可以直接得到结果。
A = np.column_stack((days, np.ones(days.size)))
B = trend_points
x = np.linalg.lstsq(A, B)[0]
案例完整代码和运行结果:
"""
demo02_lstsq.py 线性拟合 拟合股价趋势线
"""
import numpy as np
import matplotlib.pyplot as mp
import datetime as dt
import matplotlib.dates as md
# 当numpy解析文本时,将会把第一列中的每个字符串
# 都传给函数进行处理, 将处理完毕后的返回值
# 转成需要的M8[D]类型
def dmy2ymd(dmy):
dmy = str(dmy, encoding='utf-8')
# 把dmy转成日期对象
d = dt.datetime.strptime(dmy, '%d-%m-%Y')
t = d.date()
s = t.strftime('%Y-%m-%d')
return s
# 加载文件
dates, highest_prices, lowest_prices, \
closing_prices = np.loadtxt(
'../da_data/aapl.csv', delimiter=',',
usecols=(1,4,5,6), unpack=True,
dtype='M8[D], f8, f8, f8' ,
converters={1:dmy2ymd})
# 绘制收盘价
mp.figure('Linear Predict', facecolor='lightgray')
mp.title('Linear Predict', fontsize=18)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 设置主刻度定位器为每周一
ax = mp.gca()
ax.xaxis.set_major_locator(
md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(
md.DateFormatter('%Y/%m/%d'))
# 把M8[D]转为matplotlib识别的date类型
dates = dates.astype(md.datetime.datetime)
# 计算所有的趋势点
trend_points = \
(closing_prices + highest_prices + \
lowest_prices) / 3
mp.plot(dates, trend_points,
color='dodgerblue', linewidth=1,
linestyle='--', label='closing_prices')
# 线性拟合 lstsq(A, B)
days = dates.astype('M8[D]').astype(int)
A = np.column_stack((days, np.ones(days.size)))
print(A.shape)
B = trend_points
x = np.linalg.lstsq(A, B)[0]
# x[0]即是k x[1]即是b
# 绘制趋势线
trend_line = days*x[0] + x[1]
mp.plot(dates, trend_line, color='orangered',
label='TrendLine', linewidth=2)
mp.legend()
# 自动格式化x轴的日期输出
mp.gcf().autofmt_xdate()
mp.show()
如图所示:直线描述了股票走势的总体趋势。