1

私はSGDを使って簡単な多項式線形回帰モデルをピクトルで訓練しようとしていました。私はいくつかの自己完結型のコードを書いていましたが、何らかの理由で私のモデルが訓練を受けていないと思っていました。SGDを使用して単純な線形回帰モデルを訓練するにはどうすればいいですか?

私は正弦曲線からサンプリングした5点を次数4の多項式に適合させようとしています。これは凸問題です.GDまたはSGDは、列車誤差ゼロの解を最終的に見つける限り、十分に小さいステップサイズ。しかし、何らかの理由で私のモデルはうまくいきません(たとえそれがモデルのパラメータを変更しているように見えますが)。

:私も学んだ機能をプロットした、ゼロに到達することができるはずcuzの奇妙です

i = 0, current_loss = [ 2.08996224] 
i = 2000, current_loss = [ 2.03536892] 
i = 4000, current_loss = [ 2.02014995] 
i = 6000, current_loss = [ 2.01307297] 
i = 8000, current_loss = [ 2.01300406] 
i = 10000, current_loss = [ 2.01125693] 
i = 12000, current_loss = [ 2.01162267] 
i = 14000, current_loss = [ 2.01296973] 
i = 16000, current_loss = [ 2.00951076] 
i = 18000, current_loss = [ 2.00967121] 

:。

エラーが2ishに推移しそうですenter image description here

プロットのためのコード:

## 
x_horizontal = np.linspace(lb,ub,1000).reshape(1000,1) 
X_plot = poly_feat.fit_transform(x_horizontal) 
X_plot_pytorch = Variable(torch.FloatTensor(X_plot), requires_grad=False) 
## 
fig1 = plt.figure() 
#plots objs 
p_sgd, = plt.plot(x_horizontal, [ float(f_val) for f_val in mdl_sgd.forward(X_plot_pytorch).data.numpy() ]) 
p_pinv, = plt.plot(x_horizontal, np.dot(X_plot,c_pinv)) 
p_data, = plt.plot(X_train,Y_train,'ro') 
## legend 
nb_terms = c_pinv.shape[0] 
legend_mdl = f'SGD solution standard parametrization, number of monomials={nb_terms}, batch-size={M}, iterations={nb_iter}, step size={eta}' 
plt.legend(
     [p_sgd,p_pinv,p_data], 
     [legend_mdl,f'linear algebra soln, number of monomials={nb_terms}',f'data points = {N_train}'] 
    ) 
## 
plt.xlabel('x'), plt.ylabel('f(x)') 
plt.show() 

私は実際に先に行って、TensorFlowバージョンを実装しました。それはモデルを鍛えるようです。私は彼らに同じ初期設定を与えることで両者を一致させようとしました:しかし、それでも動作しませんでした。 Tensorflowコード:

graph = tf.Graph() 
with graph.as_default(): 
    X = tf.placeholder(tf.float32, [None, nb_terms]) 
    Y = tf.placeholder(tf.float32, [None,1]) 
    w = tf.Variable(tf.zeros([nb_terms,1])) 
    #w = tf.Variable(tf.truncated_normal([Degree_mdl,1],mean=0.0,stddev=1.0)) 
    #w = tf.Variable(1000*tf.ones([Degree_mdl,1])) 
    ## 
    f = tf.matmul(X,w) # [N,1] = [N,D] x [D,1] 
    #loss = tf.reduce_sum(tf.square(Y - f)) 
    loss = tf.reduce_sum(tf.reduce_mean(tf.square(Y-f), 0)) 
    l2loss_tf = (1/N_train)*2*tf.nn.l2_loss(Y-f) 
    ## 
    learning_rate = eta 
    #global_step = tf.Variable(0, trainable=False) 
    #learning_rate = tf.train.exponential_decay(learning_rate=eta, global_step=global_step,decay_steps=nb_iter/2, decay_rate=1, staircase=True) 
    train_step = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(loss) 
    with tf.Session(graph=graph) as sess: 
     Y_train = Y_train.reshape(N_train,1) 
     tf.global_variables_initializer().run() 
     # Train 
     for i in range(nb_iter): 
      #if i % (nb_iter/10) == 0: 
      if i % (nb_iter/10) == 0 or i == 0: 
       current_loss = sess.run(fetches=loss, feed_dict={X: Kern_train, Y: Y_train}) 
       print(f'i = {i}, current_loss = {current_loss}') 
      ## train 
      batch_xs, batch_ys = get_batch(Kern_train,Y_train,M) 
      sess.run(train_step, feed_dict={X: batch_xs, Y: batch_ys}) 

私も初期設定を変更しようとしたが、それはそれは大きな違いを生むべきではありませんcuzを理にかなっては何も変わりませんでした:

mdl_sgd[0].weight.data.normal_(mean=0,std=0.001) 

元の投稿:

https://discuss.pytorch.org/t/how-to-train-a-simple-linear-regression-model-with-sgd-in-pytorch-successfully/9620

これは、それがどのように見えるべきかです:

enter image description here


SOLUTION:

、ベクターの代わりに、数として返される結果に問題があると思われます問題の原因となります。つまり、次のコードは固定されたものです:

y_pred = model(batch_xs).view(-1) # change this to "y_pred = model(batch_xs)" to get the incorrect results 
    loss = (y_pred - batch_ys).pow(2).mean() 

私には完全に神秘的です。なぜこの問題が修正されたのか誰かが知っていますか?それはちょうど魔法のように思える。

+0

あなたが期待している、あなたは何を得ているどのような行動を、正確にそれらを説明してください。 –

+0

@WasiAhmad申し訳ありませんが、私はそれを明確にしませんでした。しかし、私は訓練が(線形代数解のような)実用的な解に収束することを期待しています。実際、私はTensorFlowで実装したこと、そして**私が期待した通り**正確に働いたという質問に答えました。私のPytorchコードに何か間違いがあってはならないと思います。だから短いです。なぜテンソルフローコードは動作し、Pytorchは動作しませんか? –

+0

なぜpytorch組み込みオプティマイザ(torch.optim.SGD())を使用していませんか? – Maximilian

答えて

1

バグは本当に微妙ですが、本質的には、それはナンキー放送のルールを使用しているからです。だから列ベクトル(3,1)と配列(すなわち、dimは(3,))である場合、ブロードキャストは(3,3)行列を生成することになります(行ベクトル(1,3)のベクトルを(3,)配列で減算すると、配列は処理されません行ベクトルとして)。これは、すべてのラベルとすべての予測との間のすべてのペアごとの相違の行列を計算することを意味するため、実際には悪いことです。もちろん、これは無意味であり、最初のラベルポイントの予測がデータセットの他のすべてのラベルの予測と一致することを望まないため、バグが発生します。もちろん、それは賢明なものを作りません。

答えは、訓練中やデータが供給される前に間違ったnumpy放送を避けることだけです。いずれかがうまくいくはずです。 1は、このコードを使用取り付けることができ、エラーを回避するには


def check_vectors_have_same_dimensions(Y,Y_): 
    ''' 
    Checks that vector Y and Y_ have the same dimensions. If they don't 
    then there might be an error that could be caused due to wrong broadcasting. 
    ''' 
    DY = tuple(Y.size()) 
    DY_ = tuple(Y_.size()) 
    if len(DY) != len(DY_): 
     return True 
    for i in range(len(DY)): 
     if DY[i] != DY_[i]: 
      return True 
    return False 
+0

はい、あなたはいつも 'view'や' expand_as'などを使って変数の形が本当に期待通りであることを確認してください。 – jdhao

+0

@jdhao私の問題は、私もそれが問題につながる可能性があることに全く気づいていないことだったと思います。私は、私が持っていた暗黙の仮定は、形状が何らかの方法で一致しないとエラーがスローされ、とにかく見つけ出すということでした。その前提は間違っているようです。ありがとう! –

+1

[新しい放送ルール](http://pytorch.org/docs/master/notes/broadcasting.html)がtorch 0.2.0で導入されましたが、一部のメソッドは以前のバージョンとは動作が異なります。 ['sum()'](http://pytorch.org/docs/master/torch.html#torch.sum)のようなメソッドの中には、 'keepdim = True'を使うかどうかによって出力が異なるものがあります。 – jdhao

関連する問題