最近、Pythonを使用したCourseraでのAndrew Ngの機械学習の演習3を完了しました。
演習のパート1.4から1.4.1を最初に完了すると、トレーニング済みモデルが予想される94.9%に一致する精度を持っていることを確認するのが困難になりました。デバッグして、コストと勾配関数にバグがないこと、および予測子コードが正しく機能していることを確認した後でも、精度は90.3%しかありませんでした。で共役勾配(CG)アルゴリズムを使用していましたscipy.optimize.minimize
。
好奇心から、別のアルゴリズムを試すことにし、ブロイデン-フレッチャー-ゴールドファーブ-シャノン(BFGS)を使用しました。驚いたことに、精度は大幅に96.5%に向上し、予想を上回りました。これら2つの異なる結果のCGとBFGSの比較は、ノートブックのヘッダー「最適化アルゴリズムの違いによる精度の違い」の下で確認できます。
最適化アルゴリズムの選択が異なるため、この精度の違いの理由はありますか?はいの場合、誰かが理由を説明できますか?
また、これを引き起こしている関数にバグがないことを確認するためだけにコードをレビューしていただければ幸いです。
ありがとうございました。
編集:ここで、読者にJupyterノートブックへのリンクを紹介するのではなく、このページで行うコメントのリクエストに、質問に含まれるコードを追加しました。
モデルのコスト関数:
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def compute_cost_regularized(theta, X, y, lda):
reg =lda/(2*len(y)) * np.sum(theta[1:]**2)
return 1/len(y) * np.sum(-y @ np.log(sigmoid(X@theta))
- (1-y) @ np.log(1-sigmoid(X@theta))) + reg
def compute_gradient_regularized(theta, X, y, lda):
gradient = np.zeros(len(theta))
XT = X.T
beta = sigmoid(X@theta) - y
regterm = lda/len(y) * theta
# theta_0 does not get regularized, so a 0 is substituted in its place
regterm[0] = 0
gradient = (1/len(y) * XT@beta).T + regterm
return gradient
1対すべての分類トレーニングを実装する関数:
from scipy.optimize import minimize
def train_one_vs_all(X, y, opt_method):
theta_all = np.zeros((y.max()-y.min()+1, X.shape[1]))
for k in range(y.min(),y.max()+1):
grdtruth = np.where(y==k, 1,0)
results = minimize(compute_cost_regularized, theta_all[k-1,:],
args = (X,grdtruth,0.1),
method = opt_method,
jac = compute_gradient_regularized)
# optimized parameters are accessible through the x attribute
theta_optimized = results.x
# Assign thetheta_optimized vector to the appropriate row in the
# theta_all matrix
theta_all[k-1,:] = theta_optimized
return theta_all
関数を呼び出して、さまざまな最適化方法でモデルをトレーニングします。
theta_all_optimized_cg = train_one_vs_all(X_bias, y, 'CG') # Optimization performed using Conjugate Gradient
theta_all_optimized_bfgs = train_one_vs_all(X_bias, y, 'BFGS') # optimization performed using Broyden–Fletcher–Goldfarb–Shanno
予測結果は、使用するアルゴリズムによって異なることがわかります。
def predict_one_vs_all(X, theta):
return np.mean(np.argmax(sigmoid(X@theta.T), axis=1)+1 == y)*100
In[16]: predict_one_vs_all(X_bias, theta_all_optimized_cg)
Out[16]: 90.319999999999993
In[17]: predict_one_vs_all(X_bias, theta_all_optimized_bfgs)
Out[17]: 96.480000000000004
コードを試すためにデータを取得したい人は、この投稿にリンクされているように、私のGithubで見つけることができます。