Obvious,最小特征值對應的特征向量為平面的法向
這個問題還有個關鍵是通過python求協方差矩陣的特征值和特征向量,np.linalg.eig()方法直接返回了特征值的向量和特征向量的矩陣
scipy.linalg.eigh()方法可以對返回的特征值和特征向量進行控制,通過eigvals參數,可以控制,比如我要返回最小的特征值,和其對應的特征向量,那么就是eigvals(0:0),在升序的情況下。還是很有用的。
scipy.linalg.
eigh
(a, b=None, lower=True, eigvals_only=False, overwrite_a=False, overwrite_b=False, turbo=True, eigvals=None, type=1, check_finite=True)
@author: Bambo """ import numpy as np import scipy x=[random.randint(0,100) for i in range(40)] y=[random.randint(0,100) for i in range(40)] z=[a*3+b*2+1 for a,b in zip(x,y)] r=map(list,zip(x,y,z)) k=mat(r) re=k.T*k e,v=scipy.linalg.eigh(re,turbo=False,eigvals=(0,0)) #e,v=scipy.linalg.eigh(re,eigvals=(a,b)) print e print v
下面這段代碼是當有兩個平面時,通過協方差矩陣的奇異值分解,求兩個平面的法向,測試顯示結果是正確的。
會有人問為啥你知道了平面的法向還通過奇異值分解又求了一次,為了科研。
# -*- coding: utf-8 -*- """ Created on Sun Nov 05 19:37:26 2017 @author: Bambo """ import numpy as np import scipy #隨機生成平面一上的點 x1=[np.random.randint(0,100) for i in range(400)] y1=[np.random.randint(0,100) for i in range(400)] z1=[a*3+b*2+1 for a,b in zip(x1,y1)] #隨機生成平面二上的點 x2=[np.random.randint(0,100) for i in range(400)] y2=[np.random.randint(0,100) for i in range(400)] z2=[c*3+d*2+5 for c,d in zip(x2,y2)] x1c=np.mean(x1) y1c=np.mean(y1) z1c=np.mean(z1) x2c=np.mean(x2) y2c=np.mean(y2) z2c=np.mean(z2) xc=(x1c+x2c)/2 yc=(y1c+y2c)/2 zc=(z1c+z2c)/2 #擴充成為兩個平面的點 x1[len(x1):len(x1)]=x2 y1[len(y1):len(y1)]=y2 z1[len(z1):len(z1)]=z2 x=[(x1[i]-xc) for i in range(len(x1))] y=[(y1[j]-yc) for j in range(len(y1))] z=[(z1[p]-zc) for p in range(len(z1))] print x print y print z r=map(list,zip(x,y,z)) k=np.mat(r) re=k.T*k #求最小特征值對應的特征向量 e,v=scipy.linalg.eigh(re,turbo=False,eigvals=(0,2)) #e,v=scipy.linalg.eigh(re,eigvals=(a,b)) print e print v