ゼロから作るDeep Learning Java編 第2章 パーセプトロン

# 目次
* [第1章 はじめに](https://qiita.com/saka1029/items/8c8b4bd17669e3da614a)
* [第2章 パーセプトロン](https://qiita.com/saka1029/items/bce542064073a2e6b404)
* [第3章 ニューラルネットワーク](https://qiita.com/saka1029/items/dcc40a9868d709fc6510)
* [第4章 ニューラルネットワークの学習](https://qiita.com/saka1029/items/39b13dac9f5fccd5b551)
* [第5章 誤差逆伝播法](https://qiita.com/saka1029/items/00aed8cdb557781d643a)
* 第6章 学習に関するテクニック
    * [6.1 パラメータの更新](https://qiita.com/saka1029/items/996853b91c54e0f49f09)
    * [6.2 重みの初期値](https://qiita.com/saka1029/items/d013d52deb79461855da)
    * [6.3 Batch Normalization](https://qiita.com/saka1029/items/be2645313b7e7f44e1c5)
    * [6.4 正則化](https://qiita.com/saka1029/items/36261c6784cf8ffd3ed2)
    * [6.5 ハイパーパラメータの検証](https://qiita.com/saka1029/items/1c54a5874811908659a4)
* [第7章 畳み込みニューラルネットワーク](https://qiita.com/saka1029/items/2807f76abcade7de61b4)
* [第8章 ディープラーニング](https://qiita.com/saka1029/items/7f3c0d2e503d6ca583cc)
* [最後に](https://qiita.com/saka1029/items/02175486de2213bfd5c2)

#2.3 パーセプトロンの実装

##2.3.1 簡単な実装

パーセプトロンは関数（静的メソッド）として実装できます。

```java
public static int AND(int x1, int x2) {
    double w1 = 0.5, w2 = 0.5, theta = 0.7;
    double tmp = x1 * w1 + x2 * w2;
    if (tmp <= theta)
        return 0;
    else
        return 1;
}
```

```java
assertEquals(0, AND(0, 0));
assertEquals(0, AND(1, 0));
assertEquals(0, AND(0, 1));
assertEquals(1, AND(1, 1));
```

##2.3.2 重みとバイアスの導入

ND4Jを使うと以下のようになります。

```java
INDArray x = Nd4j.create(new double[] {0, 1});
INDArray w = Nd4j.create(new double[] {0.5, 0.5});
double b = -0.7;
assertEquals("[0.00,0.50]", Util.string(w.mul(x)));
assertEquals(0.5, w.mul(x).sumNumber().doubleValue(), 0.000005);
assertEquals(-0.19999999999999996, w.mul(x).sumNumber().doubleValue() + b, 0.000005);
```

##2.3.3 重みとバイアスによる実装

「重みとバイアスによる方式」を用いれば、AND、NDND、ORゲートは次のように実装できます。

```java
public static int AND2(int x1, int x2) {
    INDArray x = Nd4j.create(new double[] {x1, x2});
    INDArray w = Nd4j.create(new double[] {0.5, 0.5});
    double b = -0.7;
    double tmp = w.mul(x).sumNumber().doubleValue() + b;
    return tmp <= 0 ? 0 : 1;
}

public static int NAND(int x1, int x2) {
    INDArray x = Nd4j.create(new double[] {x1, x2});
    INDArray w = Nd4j.create(new double[] {-0.5, -0.5});
    double b = 0.7;
    double tmp = w.mul(x).sumNumber().doubleValue() + b;
    return tmp <= 0 ? 0 : 1;
}

public static int OR(int x1, int x2) {
    INDArray x = Nd4j.create(new double [] {x1, x2});
    INDArray w = Nd4j.create(new double[] {0.5, 0.5});
    double b = -0.2;
    double tmp = w.mul(x).sumNumber().doubleValue() + b;
    return tmp <= 0 ? 0 : 1;
}
```

```java
assertEquals(0, AND2(0, 0));
assertEquals(0, AND2(1, 0));
assertEquals(0, AND2(0, 1));
assertEquals(1, AND2(1, 1));
assertEquals(1, NAND(0, 0));
assertEquals(1, NAND(1, 0));
assertEquals(1, NAND(0, 1));
assertEquals(0, NAND(1, 1));
assertEquals(0, OR(0, 0));
assertEquals(1, OR(1, 0));
assertEquals(1, OR(0, 1));
assertEquals(1, OR(1, 1));

```

#2.5 多層パーセプトロン

##2.5.2 XORゲートの実装

パーセプトロンを多層にするとXORゲートが実装できます。

```java
public static int XOR(int x1, int x2) {
    int s1 = NAND(x1, x2);
    int s2 = OR(x1, x2);
    int y = AND2(s1, s2);
    return y;
}
```

```java
assertEquals(0, XOR(0, 0));
assertEquals(1, XOR(1, 0));
assertEquals(1, XOR(0, 1));
assertEquals(0, XOR(1, 1));
```