推定量をロバスト化するには、2つのガウスrvの混合である混合ガウスモデル(GMM)として評価をモデル化します。1)真の評価、2)1に等しいジャンク評価。Scikit-learnにはすでにGMM分類器が用意されています:http : //scikit-learn.org/stable/auto_examples/mixture/plot_gmm_classifier.html#example-mixture-plot-gmm-classifier-py
もう少し掘り下げてみると、scikit-learnで評価を2つのガウス分布に分割するという簡単な方法があります。いずれかのパーティションの平均が1に近い場合、それらの評価を破棄できます。または、よりエレガントに、真の評価平均として、他の非1ガウスガウスの平均を取ることができます。
これは、これを行うipythonノートブックのコードのビットです。
from sklearn.mixture import GMM
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
import collections
def make_ratings(mean,std,rating_cnt):
rating_sample = np.random.randn(rating_cnt)*std + mean
return np.clip(rating_sample,1,5).astype(int)
def make_collection(true_mean,true_std,true_cnt,junk_count):
true_ratings = make_ratings(true_mean,true_std,true_cnt)
junk_ratings = make_ratings(1,0,junk_count)
return np.hstack([true_ratings,junk_ratings])[:,np.newaxis]
def robust_mean(X, th = 2.5, agg_th=2.5, default_agg=np.mean):
classifier = GMM(n_components=2)
classifier.fit(X)
if np.min(classifier.means_) > th or default_agg(X)<agg_th:
return default_agg(X)
else:
return np.max(classifier.means_)
r_mean = 4.2
X = make_collection(r_mean,2,40,10)
plt.hist(X,5)
classifier = GMM(n_components=2)
classifier.fit(X)
plt.show()
print "vars =",classifier.covars_.flatten()
print "means = ",classifier.means_.flatten()
print "mean = ",np.mean(X)
print "median = ",np.median(X)
print "robust mean = ", robust_mean(X)
print "true mean = ", r_mean
print "prob(rating=1|class) = ",classifier.predict_proba(1).flatten()
print "prob(rating=true_mean|class) = ",classifier.predict_proba(r_mean).flatten()
print "prediction: ", classifier.predict(X)
1回の実行の出力は次のようになります。
vars = [ 0.22386589 0.56931527]
means = [ 1.32310978 4.00603523]
mean = 2.9
median = 3.0
robust mean = 4.00603523034
true mean = 4.2
prob(rating=1|class) = [ 9.99596493e-01 4.03507425e-04]
prob(rating=true_mean|class) = [ 1.08366762e-08 9.99999989e-01]
prediction: [1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0 1 1 0 1 1 1 0 1 0 1 0 1 1 0
1 1 1 0 0 0 0 0 0 0 0 0 0]
これがいくつかのモンテカルロトライアルでどのように機能するかをシミュレーションできます。
true_means = np.arange(1.5,4.5,.2)
true_ratings = 40
junk_ratings = 10
true_std = 1
m_out = []
m_in = []
m_reg = []
runs = 40
for m in true_means:
Xs = [make_collection(m,true_std,true_ratings,junk_ratings) for x in range(runs)]
m_in.append([[m]*runs])
m_out.append([[robust_mean(X, th = 2.5, agg_th=2,default_agg=np.mean) for X in Xs]])
m_reg.append([[np.mean(X) for X in Xs]])
m_in = np.array(m_in).T[:,0,:]
m_out = np.array(m_out).T[:,0,:]
m_reg = np.array(m_reg).T[:,0,:]
plt.plot(m_in,m_out,'b.',alpha=.25)
plt.plot(m_in,m_reg,'r.',alpha=.25)
plt.plot(np.arange(0,5,.1),np.arange(0,5,.1),'k.')
plt.xlim([0,5])
plt.ylim([0,5])
plt.xlabel('true mean')
plt.ylabel('predicted mean')
plt.title("true_ratings=" + str(true_ratings)
+ "; junk_ratings=" + str(junk_ratings)
+ "; std="+str(true_std))
出力は以下に貼り付けられます。赤は平均評価で、青は提案された評価です。パラメータを微調整して、わずかに異なる動作を取得できます。