1、拉格朗日插值法
考虑全局信息的比较经典的插值方法,编程简单,计算量大。
#coding=utf-8
from matplotlib import pyplot as plt
def Lg(data,testdata):
predict=0
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
if testdata in data_x:
#print "testdata is already known"
return data_y[data_x.index(testdata)]
for i in range(len(data_x)):
af=1
for j in range(len(data_x)):
if j!=i:
af*=(1.0*(testdata-data_x[j])/(data_x[i]-data_x[j]))
predict+=data_y[i]*af
return predict
def plot(data,nums):
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
Area=[min(data_x),max(data_x)]
X=[Area[0]+1.0*i*(Area[1]-Area[0])/nums for i in range(nums)]
X[len(X)-1]=Area[1]
Y=[Lg(data,x) for x in X]
plt.plot(X,Y,label='result')
for i in range(len(data_x)):
plt.plot(data_x[i],data_y[i],'ro',label="point")
plt.savefig('Lg.jpg')
plt.show()
data=[[0,0],[1,2],[2,3],[3,8],[4,2]]
print Lg(data,1.5)
plot(data,100)
2、牛顿插值
相比于拉格朗日的优势在于 牛顿插值法在重新引入数据时可以仅仅更新F矩阵进行。(手动维护差商表的话,效率提高很多,但对计算机而言,觉得差不多)。复杂度和拉格朗日一样,O(n2)。
#coding=utf-8
from matplotlib import pyplot as plt
def calF(data):
#差商计算 n个数据 0-(n-1)阶个差商 n个数据
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
F= [1 for i in range(len(data))]
FM=[]
for i in range(len(data)):
FME=[]
if i==0:
FME=data_y
else:
for j in range(len(FM[len(FM)-1])-1):
delta=data_x[i+j]-data_x[j]
value=1.0*(FM[len(FM)-1][j+1]-FM[len(FM)-1][j])/delta
FME.append(value)
FM.append(FME)
F=[fme[0] for fme in FM]
print FM
return F
def NT(data,testdata,F):
#差商之类的计算
predict=0
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
if testdata in data_x:
return data_y[data_x.index(testdata)]
else:
for i in range(len(data_x)):
Eq=1
if i!=0:
for j in range(i):
Eq=Eq*(testdata-data_x[j])
predict+=(F[i]*Eq)
return predict
def plot(data,nums):
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
Area=[min(data_x),max(data_x)]
X=[Area[0]+1.0*i*(Area[1]-Area[0])/nums for i in range(nums)]
X[len(X)-1]=Area[1]
F=calF(data)
Y=[NT(data,x,F) for x in X]
plt.plot(X,Y,label='result')
for i in range(len(data_x)):
plt.plot(data_x[i],data_y[i],'ro',label="point")
plt.savefig('Newton.jpg')
plt.show()
data=[[0,0],[1,2],[2,3],[3,8],[4,2]]
plot(data,100)
3、分段线性插值
最简单,工业使用最多。
#coding=utf-8
from matplotlib import pyplot as plt
def DivideLine(data,testdata):
#找到最邻近的
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
if testdata in data_x:
return data_y[data_x.index(testdata)]
else:
index=0
for j in range(len(data_x)):
if data_x[j]<testdata and data_x[j+1]>testdata:
index=j
break
predict=1.0*(testdata-data_x[j])*(data_y[j+1]-data_y[j])/(data_x[j+1]-data_x[j])+data_y[j]
return predict
def plot(data,nums):
data_x=[data[i][0] for i in range(len(data))]
data_y=[data[i][1] for i in range(len(data))]
Area=[min(data_x),max(data_x)]
X=[Area[0]+1.0*i*(Area[1]-Area[0])/nums for i in range(nums)]
X[len(X)-1]=Area[1]
Y=[DivideLine(data,x) for x in X]
plt.plot(X,Y,label='result')
for i in range(len(data_x)):
plt.plot(data_x[i],data_y[i],'ro',label="point")
plt.savefig('DivLine.jpg')
plt.show()
data=[[0,0],[1,2],[2,3],[3,8],[4,2]]
print DivideLine(data,1.5)
plot(data,100)
