线性模型拟合笔记
我們大學(xué)以前學(xué)到的函數(shù)大多都是單調(diào)的一個(gè)函數(shù)曲線,偶爾遇到分類討論的函數(shù)等等,但如果在實(shí)際運(yùn)用中,我們很難找到一個(gè)對(duì)應(yīng)現(xiàn)實(shí)數(shù)據(jù)的曲線來(lái)表示我們想要表示的函數(shù),更別說(shuō)利用類似的曲線建立模型,預(yù)測(cè)數(shù)據(jù)了。
因而,我們需要運(yùn)用數(shù)據(jù)算法來(lái)建立許多個(gè)y=ax+b這樣的函數(shù),然后通過(guò)一定的篩選,運(yùn)算,來(lái)計(jì)算出來(lái)我們所需要的擬合過(guò)的線性函數(shù)。
1.1線性模型預(yù)測(cè)
要學(xué)會(huì)用線性模型預(yù)測(cè),我們得先處理好數(shù)據(jù)來(lái)得到我們需要的y=kx+b的系數(shù)等等
首先我們先介紹np.linalg.lstsq(A,B)[0],這個(gè)函數(shù)功能性很強(qiáng)
不過(guò)我們得先得到X和Y的值,這里的xy就是對(duì)應(yīng)上述公式中的AB。而這里X里右邊加了一列1就是為了能在矩陣相乘的時(shí)候得到y(tǒng)=kx+b這樣比較干凈的式子,這里可以通過(guò)實(shí)例介紹一下。
date=np.linspace(1,31,30)
np.random.seed(1)
h=np.random.randint(1,100,size=30)
plt.figure('random stock',facecolor='lightgray')
plt.title('random stock',fontsize=18)
plt.xlabel('日期',fontsize=14)
plt.ylabel('股值',fontsize=14)
plt.grid()
plt.gca().xaxis.set_major_formatter(ticker.FormatStrFormatter('%.f日'))
plt.gca().yaxis.set_major_formatter(ticker.FormatStrFormatter('%.f比率'))
mean=np.mean(h)
plt.plot(date,h,label='Actual'
??????? ,color='r'
??????? ,ls='--',alpha=0.2)
#整理A和B
N=4
pred_price=np.zeros(30-N*2)
for i in range(pred_price.size):
??? A=np.zeros((N,N))
??? for j in range(N):
??????? A[j, ]=h[i+j:i+j+N]
??? B=h[i+N:i+N*2]
??? x=np.linalg.lstsq(A,B)[0]
??? pred=B.dot(x)
??? pred_price[i]=pred
print(x)
print(A)
print(B)
#預(yù)測(cè)
print(pred_price)
#實(shí)際
plt.plot(date[N*2:],pred_price,
??????? marker='o',color='orangered',
??????? label='Prediction')
?
輸出值:
x:[-0.88450763 1.04683535 1.0525915 -0.28124775] A:[[15. 51. 69. 88.][51. 69. 88. 88.][69. 88. 88. 95.][88. 88. 95. 97.]] B:[88 95 97 87] pred_price:[ 6.46750295e+03 -5.55541783e+03 3.14212281e+02 7.57373027e+01-2.29655198e+01 -5.24244331e+00 9.29324887e+01 -1.06184268e+019.23510942e+00 5.64371349e+01 3.39752190e+02 1.09966123e+011.17850355e+02 3.62349967e+02 1.71766016e+01 3.60095747e+021.50182872e+02 1.55346049e+02 1.68522321e+02 1.07359014e+021.07221832e+02 9.92455079e+01]這里我們選用n=4來(lái)進(jìn)行擬合,我們也可以改變n的值來(lái)看n為多少時(shí)曲線更能擬合。
這里我們 x=np.linalg.lstsq(A,B)[0],因此x的值就是函數(shù)里的k和b的集合,然后將B.dot(x)就是將矩陣數(shù)字相乘后相加,完成了kx+b的步驟,因此我們可以得到pred值,這個(gè)值因?yàn)槲覀冊(cè)瘮?shù)里有實(shí)際值,所以可以進(jìn)行一定的對(duì)比,幾乎是近似的,因此說(shuō)明擬合曲線有一定的效果
1.2趨勢(shì)線
當(dāng)我們并不需要完全擬合數(shù)據(jù),單純就是表現(xiàn)函數(shù)趨勢(shì)的時(shí)候我們會(huì)選用趨勢(shì)線
date,opening_price,highest_price,lowest_price,closing_price=np.loadtxt('30a.csv'
????????? ,delimiter=','
????????? ,usecols=(0,1,2,4,3),
????????? unpack=True,
????????? dtype='M8[D],f8,f8,f8,f8',
????????? )
days=date.astype(int)
print(len(days))
trendprice=(highest_price+lowest_price+closing_price)/3
plt.xticks(rotation=45)
plt.plot(date,closing_price,label='Actual'
??????? ,color='r'
??????? ,ls='--',alpha=0.5??????? )
plt.scatter(date,trendprice,label='Trend',
?????????? color='b',marker='D',
?????????? s=80)
A=np.column_stack((days,np.ones_like(days)))
B=trendprice
x=np.linalg.lstsq(A,B)[0]
trend_line=x[0]*days +x[1]
plt.plot(date,trend_line,
??????? color='g',label='TrendLine')??????? ?
plt.gcf()
不過(guò)在這里我們首先是先求出了趨勢(shì)點(diǎn),把每天的收盤(pán)價(jià)最高價(jià)最低價(jià)求了平均值,然后通過(guò)散點(diǎn)圖進(jìn)行標(biāo)記
A=np.column_stack((days,np.ones_like(days)))注意這里的column_stack,其實(shí)就是對(duì)于我前面說(shuō)的將X中右邊一列全都化成1來(lái)方便后續(xù)進(jìn)行計(jì)算,然后是用1.1里介紹的linalg.lstsq來(lái)求得k和b這里直接用x【0】表示k,x【1】表示b,然后算出trendline的函數(shù)曲線
2.多函數(shù)運(yùn)算
2.1協(xié)方差
在面對(duì)兩個(gè)股票的時(shí)候,我們可以通過(guò)計(jì)算協(xié)方差來(lái)判斷他們的趨勢(shì),他們的相關(guān)性大小等等,借此我們有時(shí)可以通過(guò)一個(gè)股票來(lái)預(yù)測(cè)另外一個(gè)股票的趨勢(shì)
?這里我們可以通過(guò)兩組隨機(jī)數(shù)初步認(rèn)識(shí)協(xié)方差的計(jì)算步驟,首先我們得算出平均數(shù),接著離差就是原數(shù)組和平均數(shù)的差,最后cov就是我們的協(xié)方差,協(xié)方差為正就說(shuō)明兩個(gè)數(shù)組正相關(guān),一個(gè)越大,另外一個(gè)也越大
2.2相關(guān)系數(shù),相關(guān)矩陣,協(xié)方差矩陣
?相關(guān)系數(shù)是基于協(xié)方差基礎(chǔ)之上的,相關(guān)系數(shù)絕對(duì)值越大,說(shuō)明兩個(gè)函數(shù)的關(guān)系越強(qiáng),反之則越弱
相關(guān)矩陣則是根據(jù)相關(guān)系數(shù)來(lái)構(gòu)成的,主對(duì)角線上為1,就是函數(shù)與自己的相關(guān)性,副對(duì)角線上就是兩個(gè)函數(shù)對(duì)各自的相關(guān)系數(shù)
協(xié)方差矩陣和協(xié)方差的數(shù)據(jù)稍微有點(diǎn)不同,因?yàn)閱渭儏f(xié)方差運(yùn)算時(shí),只靠樣本來(lái)運(yùn)算,而協(xié)方差矩陣時(shí)總體數(shù)組進(jìn)行計(jì)算,因此數(shù)據(jù)會(huì)有所偏差
這里我們通過(guò)實(shí)例來(lái)了解一下
date,aclosing_price=np.loadtxt('30a.csv'
????????? ,delimiter=','
????????? ,usecols=(0,3),
????????? unpack=True,
????????? dtype='M8[D],f8',
????????? )
bclosing_price=np.loadtxt('30b.csv'
????????? ,delimiter=','
????????? ,usecols=(3),
????????? unpack=True,
????????? dtype='f8',
????????? )
#繪制收盤(pán)價(jià)折線圖
plt.figure('COV',facecolor='lightgray')
plt.title('COV',fontsize=18)
plt.xlabel('date',fontsize=14)
plt.ylabel('closingprice',fontsize=14)
plt.grid(ls=":")
import matplotlib.dates as md
ax=plt.gca()
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %y'))
ax.xaxis.set_minor_locator(md.DayLocator())
date=date.astype(md.datetime.datetime)
plt.plot(date,aclosing_price,label='a30股票'
??????? ,color='r'
??????? ,ls='--',alpha=0.5??????? )
plt.plot(date,bclosing_price,label='b30股票'
??????? ,color='b'
??????? ,ls='-',alpha=0.5??????? )
#計(jì)算兩只股票協(xié)方差
#平均值
ave_a=aclosing_price.mean()
ave_b=bclosing_price.mean()
#離差
dev_a=aclosing_price-ave_a
dev_b=bclosing_price-ave_b
#協(xié)方差
cov=np.mean(dev_a*dev_b)
print(cov)
#相關(guān)系數(shù)
coef=cov/(np.std(aclosing_price)*np.std(bclosing_price))
print(coef)
#相關(guān)矩陣
m=np.corrcoef(aclosing_price ,bclosing_price)
print(m)
#協(xié)方差矩陣
print(np.cov(aclosing_price ,bclosing_price))
可以看到輸出的第二個(gè)就是相關(guān)系數(shù),與第三個(gè)輸出的相關(guān)系數(shù)的副對(duì)角線上數(shù)值相同,而協(xié)方差矩陣中0.0018稍微比樣本運(yùn)算的0.0017稍微大了一點(diǎn)也可見(jiàn)一斑,計(jì)算上并不會(huì)有太大影響。
3.多項(xiàng)式擬合
3.1polyfit,polyval,polyder,roots方法
在了解多項(xiàng)式擬合的時(shí)候,我們得先了解這個(gè)過(guò)程
1).#根據(jù)一組樣本,給出最高次冪,求出擬合系數(shù)
np.polyfit(x,y,最高次冪)->P
這里的P就是y=kx**n+k1x**中的未知數(shù)系數(shù)【k,k1】這樣,當(dāng)我們已知x和y的時(shí)候,可以規(guī)定一個(gè)最高次冪類似于3,4這樣來(lái)得到P
2)#根據(jù)擬合系數(shù)和自變量求得擬合數(shù)
np.polyval(P,X)->y'
我們要注意,這里的y是y’了,是我們想要擬合的函數(shù)的y而不是原函數(shù)的y,通過(guò)剛剛第一步求得的P,就可以算出來(lái)y‘
3)#根據(jù)擬合系數(shù)求得多項(xiàng)式導(dǎo)函數(shù)的導(dǎo)數(shù)
np.polyder(P)->Q
相比大學(xué)里學(xué)用的導(dǎo)數(shù),這里只用一個(gè)公式就可以算出來(lái)函數(shù)對(duì)于x的一階求導(dǎo)后函數(shù)的系數(shù),算是很方便的式子
4)#已知多項(xiàng)式系數(shù)Q求得函數(shù)根
np.root(Q)->根
最后一步就是通過(guò)剛剛我們求得到的Q來(lái)算出原方程的根,即函數(shù)k為0的時(shí)候類似的解
P=[4,3,-1000,1]
x=np.linspace(-20,20,1000)
y=np.polyval(P,x)
Q=np.polyder(P)
xs=np.roots(Q)
ys=np.polyval(P,xs)
plt.plot(x,y,label='原函數(shù)')
plt.scatter(xs,ys,label='根函數(shù)',c='r',s=100)
通過(guò)這個(gè)方法,我們就可以找到函數(shù)的根
3.2擬合函數(shù)
其實(shí)在剛剛3.1中就涉及到了擬合函數(shù)的概念,我們可以通過(guò)P和X來(lái)得到擬合過(guò)的線性函數(shù)
date,aclosing_price=np.loadtxt('30a.csv'
????????? ,delimiter=','
????????? ,usecols=(0,3),
????????? unpack=True,
????????? dtype='M8[D],f8',
????????? )
bclosing_price=np.loadtxt('30b.csv'
????????? ,delimiter=','
????????? ,usecols=(3),
????????? unpack=True,
????????? dtype='f8',
????????? )
ax=plt.gca()
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %y'))
ax.xaxis.set_minor_locator(md.DayLocator())
date=date.astype(md.datetime.datetime)
#繪制差價(jià)函數(shù)曲線
diff_price=aclosing_price-bclosing_price
plt.plot(date,diff_price,c='dodgerblue',label='差價(jià)函數(shù)曲線')
#擬合差價(jià)函數(shù)
days=date.astype('M8[D]').astype('int32')
P=np.polyfit(days,diff_price,20)
poly_price=np.polyval(P,days)
plt.plot(date,poly_price,label='擬合差價(jià)函數(shù)'
??????? ,color='r'
??????? ,ls='--',alpha=0.5,linewidth=2??? )
?
這里的poly_price就是新擬合出來(lái)的y’,對(duì)待兩個(gè)股票的差價(jià)組成的函數(shù),我們可以通過(guò)線性擬合函數(shù)得知函數(shù)的趨勢(shì)以及預(yù)測(cè)數(shù)據(jù)
?
?
?
總結(jié)
- 上一篇: 解决windows10和ubuntu双系
- 下一篇: 压缩或者解压带密码的ZIp包