表題の通りです。
まずsklearnのLDAについて
LDA自体の説明について
結論
1次元の2値(bool)分類でのLDAの場合、xの値がある値以上ならTrue,未満ならFalseと予想するという内部構造になります。
そのある値なんですが、以下のようにモデルから取り出すことができます。
border = -model.intercept_/model.coef_
傾きがmodel.coef_
で切片がmodel.intercept_
、それぞれa,bとおくと
$$ax_{border}+b=0\ \ ,\ x_{border}=-b/a$$
な感じです。
solverはsvd,lsqr,eigenの3種類で標準はsvd。見ていきましょう。
#make_moonsで的当にデータ作成、特に意味はない
n_samples=100
X, y = make_moons(n_samples = n_samples, noise = 0.1)
X=X[:,[0]]
#TrueとFalseのバランスを1:1じゃなくする。
random_y=np.random.randint(0,2,n_samples)
print(f"n_True:n_False={np.sum(random_y==1)}:{np.sum(random_y==0)}")
>>n_True:n_False=53:47
#svd
model_svd=LDA(solver="svd")
model_svd.fit(X, random_y).score(X, random_y)
print(-model_svd.intercept_/model_svd.coef_)
>>[[-0.3641749]]
#lsqr
model_lsqr=LDA(solver="lsqr")
model_lsqr.fit(X, random_y).score(X, random_y)
print(-model_lsqr.intercept_/model_lsqr.coef_)
>>[[-0.34673599]]
#eigen
model_eigen=LDA(solver="eigen")
model_eigen.fit(X, random_y).score(X, random_y)
print(-model_eigen.intercept_/model_eigen.coef_)
>>[[-0.34673599]]
なんでかは知らないですが、svdの時だけ値が変わります。
そして、上記サイトの原理の通り作成するとlsqr,eigenの値と一致します。
ただし、TrueとFalseが同じ数だけある時には全て一致します。
経緯
以上のページを参考に、自分でLDAを実装しようとしました。
手始めにまず1次元の、2値(bool)分類で作成
以下のようになりました。
def LDA_1d(x,y):
mu_T=np.mean(x[y])
mu_F=np.mean(x[~y])
sigma=(np.sum((x[y]-mu_T)**2)+np.sum((x[~y]-mu_F)**2))/(y.shape[0])
f=(mu_T-mu_F)*x-(mu_T-mu_F)*(mu_T+mu_F)/2+sigma*np.log(np.sum(y)/np.sum(~y))
return np.sum((f>=0)==y)/y.shape[0]
これをsklearnのものでチェックした時に、おかしいと言われてしまいます。
雑にですが、
N=10
for i in range(N):
#データ作成、make_moonsで的当にXを作成して、random_yで的当に答えを作成
n_samples=100
X, y = make_moons(n_samples = n_samples, noise = 0.1)
X=X[:,[0]]
random_y=np.random.randint(0,2,n_samples)
#入れてみる
my_score_LDA=LDA_1d(X[:,0], random_y==1) #myfunc
ans_score_LDA=model_LDA.fit(X, random_y).score(X, random_y) #sklearn
if my_score_LDA!=ans_score_LDA:
print(f"diff_LDA(random),{np.sum(random_y==0)}:{np.sum(random_y==1)}" ,my_score_LDA,ans_score_LDA)
動かしてみたらdiff_LDA
が表示されまくります。
いろいろ1日以上悩んでふと、solver
なんて引数があったなーと思い、変更してみました。
その際に上の値を見て確信しました。かなり時間を無駄にしてしまいました。
だってsolverで変わるなんて流石に思わなくないですか??
以上です。何か誤解があったら(ありそう)教えていただければと思います。