機械学習で二次方程式の解 3

![二次方程式.png](https://qiita-image-store.s3.amazonaws.com/0/207542/49af06a1-d0fe-2faf-d631-c950ba383c5e.png)

前回からの改善点
・重みを配列にしていたが縦と横を混乱し間違っていたのを修正
・変数名をわかりやすく
・誤差逆伝播の掛け算の順番をわかりやすく

最終的な重みの値
w0_a_h0 -133.428004259993
w0_a_h1 -133.428004259993
w0_a_h2 -133.428004259993
w0_b_h0 89474.2089591783
w0_b_h1 89474.2089591783
w0_b_h2 89474.2089591783
w0_c_h0 -4191359.76820174
w0_c_h1 -4191359.76820174
w0_c_h2 -4191359.76820174
w0_B_h0 -133.428004259993
w0_B_h1 -133.428004259993
w0_B_h2 -133.428004259993

w1_h0_OUT0 -4.35151574009807
w1_h0_OUT1 -0.657661707278884
w1_h1_OUT0 -4.35151574009807
w1_h1_OUT1 -0.657661707278884
w1_h2_OUT0 -4.35151574009807
w1_h2_OUT1 -0.657661707278884
w1_B_OUT0 100
w1_B_OUT1 99

次回
層を増やしてどうなるか

```csharp
        double[,] w0 = new double[,]{
                                        { 0.5,0.5,0.5},
                                        { 0.5,0.5,0.5},
                                        { 0.5,0.5,0.5},
                                        { 0.5,0.5,0.5}};

        double[,] w1 = new double[,]{
                                        { 0.5,0.5},
                                        { 0.5,0.5},
                                        { 0.5,0.5},
                                        { 0.5,0.5}};

        private void nnw()
        {
            for (double alpha = 0; alpha <= 100; alpha++)
            {
                for (double beta = 0; beta <= 100; beta++)
                {
                    //
                    double a = 1;
                    double b = -(alpha + beta);
                    double c = alpha * beta;
                    double d = b * b - 4 * a * c;

                    //forward
                    double h0_0_in = a * w0[0, 0] + b * w0[1, 0] + c * w0[2, 0] + w0[3, 0];
                    double h0_1_in = a * w0[0, 1] + b * w0[1, 1] + c * w0[2, 1] + w0[3, 1];
                    double h0_2_in = a * w0[0, 2] + b * w0[1, 2] + c * w0[2, 2] + w0[3, 2];

                    double h0_0_out = s(h0_0_in);
                    double h0_1_out = s(h0_1_in);
                    double h0_2_out = s(h0_2_in);

                    double OUT0_in = h0_0_out * w1[0, 0] + h0_1_out * w1[1, 0] + h0_2_out * w1[2, 0] + w1[3, 0];
                    double OUT1_in = h0_0_out * w1[0, 1] + h0_1_out * w1[1, 1] + h0_2_out * w1[2, 1] + w1[3, 1];

                    double OUT0_out = OUT0_in;
                    double OUT1_out = OUT1_in;

                    double[] mE = new double[] { alpha - OUT0_out, beta - OUT1_out };

                    Invoke(new dldl(delegate
                    {
                        dataGridView1.Rows.Add(
                            a.ToString(), b.ToString(), c.ToString(), d.ToString(),
                            alpha.ToString(), beta.ToString(),
                            w0[0, 0].ToString(), w0[0, 1].ToString(), w0[0, 2].ToString(),
                            w0[1, 0].ToString(), w0[1, 1].ToString(), w0[1, 2].ToString(),
                            w0[2, 0].ToString(), w0[2, 1].ToString(), w0[2, 2].ToString(),
                            w0[3, 0].ToString(), w0[3, 1].ToString(), w0[3, 2].ToString(),
                            h0_0_in.ToString(), h0_0_out.ToString(),
                            h0_1_in.ToString(), h0_1_out.ToString(),
                            h0_2_in.ToString(), h0_2_out.ToString(),
                            w1[0, 0].ToString(), w1[0, 1].ToString(),
                            w1[1, 0].ToString(), w1[1, 1].ToString(),
                            w1[2, 0].ToString(), w1[2, 1].ToString(),
                            w1[3, 0].ToString(), w1[3, 1].ToString(),
                            OUT0_in.ToString(), OUT0_out.ToString(),
                            OUT1_in.ToString(), OUT1_out.ToString(),
                            mE[0].ToString(), mE[1].ToString()
                            );
                        Refresh();
                    }));

                    //backward
                    w0[0, 0] = w0[0, 0] - (a * s(-h0_0_out) * (1 - s(-h0_0_out)) * ((w1[0, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));
                    w0[0, 1] = w0[0, 1] - (a * s(-h0_1_out) * (1 - s(-h0_1_out)) * ((w1[1, 0] * -mE[0]) + (w1[1, 1] * -mE[1])));
                    w0[0, 2] = w0[0, 2] - (a * s(-h0_2_out) * (1 - s(-h0_2_out)) * ((w1[2, 0] * -mE[0]) + (w1[2, 1] * -mE[1])));

                    w0[1, 0] = w0[1, 0] - (b * s(-h0_0_out) * (1 - s(-h0_0_out)) * ((w1[0, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));
                    w0[1, 1] = w0[1, 1] - (b * s(-h0_1_out) * (1 - s(-h0_1_out)) * ((w1[1, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));
                    w0[1, 2] = w0[1, 2] - (b * s(-h0_2_out) * (1 - s(-h0_2_out)) * ((w1[2, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));

                    w0[2, 0] = w0[2, 0] - (c * s(-h0_0_out) * (1 - s(-h0_0_out)) * ((w1[0, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));
                    w0[2, 1] = w0[2, 1] - (c * s(-h0_1_out) * (1 - s(-h0_1_out)) * ((w1[1, 0] * -mE[0]) + (w1[1, 1] * -mE[1])));
                    w0[2, 2] = w0[2, 2] - (c * s(-h0_2_out) * (1 - s(-h0_2_out)) * ((w1[2, 0] * -mE[0]) + (w1[2, 1] * -mE[1])));

                    w0[3, 0] = w0[3, 0] - (    s(-h0_0_out) * (1 - s(-h0_0_out)) * ((w1[0, 0] * -mE[0]) + (w1[0, 1] * -mE[1])));
                    w0[3, 1] = w0[3, 1] - (    s(-h0_1_out) * (1 - s(-h0_1_out)) * ((w1[1, 0] * -mE[0]) + (w1[1, 1] * -mE[1])));
                    w0[3, 2] = w0[3, 2] - (    s(-h0_2_out) * (1 - s(-h0_2_out)) * ((w1[2, 0] * -mE[0]) + (w1[2, 1] * -mE[1])));


                    w1[0, 0] = w1[0, 0] - (h0_0_out * -mE[0]);
                    w1[1, 0] = w1[1, 0] - (h0_1_out * -mE[0]);
                    w1[2, 0] = w1[2, 0] - (h0_2_out * -mE[0]);
                    w1[3, 0] = w1[3, 0] - (-mE[0]);

                    w1[0, 1] = w1[0, 1] - (h0_0_out * -mE[1]);
                    w1[1, 1] = w1[1, 1] - (h0_1_out * -mE[1]);
                    w1[2, 1] = w1[2, 1] - (h0_2_out * -mE[1]);
                    w1[3, 1] = w1[3, 1] - (-mE[1]);
                }
            }

            Invoke(new dldl(delegate
            {
                button1.Enabled = true;
            }));
        }

        private double s(double x)
        {
            return 1.0/(1.0 + Math.Exp(-x));
        }

        private delegate void dldl();

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            //列ヘッダーかどうか調べる
            if (e.ColumnIndex < 0 && e.RowIndex >= 0)
            {
                //セルを描画する
                e.Paint(e.ClipBounds, DataGridViewPaintParts.All);

                //行番号を描画する範囲を決定する
                //e.AdvancedBorderStyleやe.CellStyle.Paddingは無視しています
                Rectangle indexRect = e.CellBounds;
                indexRect.Inflate(-2, -2);
                //行番号を描画する
                TextRenderer.DrawText(e.Graphics,
                    (e.RowIndex + 1).ToString(),
                    e.CellStyle.Font,
                    indexRect,
                    e.CellStyle.ForeColor,
                    TextFormatFlags.Right | TextFormatFlags.VerticalCenter);
                //描画が完了したことを知らせる
                e.Handled = true;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            Thread th = new Thread(nnw);
            th.Start();
        }
        
```