深層学習 Sequential モデル を使ってみる 

## Sequential モデル について

Sequentialモデルとは、コンピュータプログラムの一種で、その名前は「順番に」という意味があります。このプログラムは、特別な問題を解決するために作られたものです。それは、たくさんの層を持っていて、それぞれの層は次の層につながっています。ちょうど、レゴブロックを積み上げていくようなイメージです。

このSequentialモデルは、画像や音声などのデータを分析して、何か特定のことを見つけるのに役立ちます。例えば、写真から猫を見つけることができます。これは、コンピュータが学習して、自分で考える力を持っているからです。

まず、コンピュータはたくさんのデータ（情報）を見ます。それから、Sequentialモデルの中の層にデータを入れます。データは、一つの層から次の層へと順番に進んでいきます。その過程で、コンピュータはデータをよく見て、何か特徴やパターンを見つけます。

最後の層にたどり着くと、コンピュータはその特徴やパターンをもとに、答えを出します。例えば、「この写真には猫がいる」とか、「この音は鳥の鳴き声だ」という答えです。

これが、Sequentialモデルの簡単な説明です。コンピュータがSequentialモデルを使って、私たちの世界を理解しようとしています。そして、そのおかげで、私たちはいろいろなことができるようになります。例えば、携帯電話で写真を撮ると、自動的に写真の中の人や物を認識したり、音声を聞いて文章に変換できたりするのです。


## Sequential モデル について詳しく

Sequential モデルは、ニューラルネットワークを構築するための方法の一つです。

ニューラルネットワークは、複数の層（レイヤー）で構成されており、各層は前の層からの入力を受け取り、出力を生成します。Sequential モデルは、このような層を一直線に繋げて構成されるモデルであり、一つの入力から一つの出力を生成することができます。

例えば、画像分類の問題では、Sequential モデルを使って、画像を入力とし、それがどのクラスに属するかを出力することができます。

Sequential モデルは、Keras という機械学習ライブラリで提供されており、簡単にモデルを構築することができます。また、層を追加したり、ハイパーパラメーターを調整したりすることも簡単にできます。

```
def adjust_model(input_shape, n_classes):
    # まず、ハイパーパラメータの範囲を定義します（どのような数字の組み合わせでモデルを作るか）
    dense_units = [input_shape*2, input_shape*3]
    dropout_rates = [0.2, 0.3, 0.4]
    learning_rates = [0.001, 0.01, 0.1]

    # 次に、ハイパーパラメータをランダムに選びます
    dense_units = np.random.choice(dense_units)
    dropout_rate1 = np.random.choice(dropout_rates)
    dropout_rate2 = np.random.choice(dropout_rates)
    learning_rate = np.random.choice(learning_rates)

    # 選ばれたハイパーパラメータを使って、Sequentialモデルを作ります
    model = models.Sequential()
    model.add(layers.Dense(dense_units, activation='relu', input_shape=(input_shape,))) # 入力層を追加
    model.add(layers.Dropout(dropout_rate1)) # ドロップアウト層を追加（過学習を防ぐ）
    model.add(layers.Dense(dense_units, activation='relu')) # 隠れ層を追加
    model.add(layers.Dropout(dropout_rate2)) # もう一つのドロップアウト層を追加
    model.add(layers.Dense(n_classes, activation='softmax')) # 出力層を追加

    # 選ばれたハイパーパラメータでモデルをコンパイルします（モデルがどのように学習するかを決める）
    optimizer = optimizers.Adam(lr=learning_rate) # オプティマイザーを選びます（学習方法）
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) # モデルをコンパイル

    return model # モデルを返します

# adjust_model関数を使ってモデルを作成します
model = adjust_model(input_shape=5, n_classes=2)

```

このコードは、機械学習モデルを調整するための関数「adjust_model」を定義しています。

関数は、2つの引数「input_shape」と「n_classes」を取ります。input_shapeは入力データの形状を指定し、n_classesはモデルが分類するクラスの数を指定します。

この関数は、モデルのパフォーマンスを向上させるために、ハイパーパラメータの最適な組み合わせを探索します。ハイパーパラメータとは、モデルの設定に関するパラメータのことで、訓練中に調整する必要があります。

関数内で、dense_units、dropout_rates、learning_ratesという3つのハイパーパラメータの探索範囲を定義します。次に、np.random.choiceを使用して、それらの範囲内からランダムに値をサンプリングして、ランダムに選択されたハイパーパラメータでモデルを構築します。

最後に、Adam最適化器を使用してモデルをコンパイルし、その結果を返します。

最後の行は、関数を呼び出し、引数input_shape=5、n_classes=2でモデルを調整するという意味です。

## 具体的に説明

具体的には、以下のような処理が行われています。

入力の形状とクラス数を引数として、adjust_model 関数を定義します。

ハイパーパラメーターの範囲を定義します。具体的には、密な層のユニット数、ドロップアウト率、学習率の範囲を定義します。

ハイパーパラメーターをランダムに選択します。密な層のユニット数、2つのドロップアウト率、学習率をランダムに選択します。

ランダムに選択されたハイパーパラメーターを使用して、Sequential モデルを構築します。Sequential モデルは、一連のレイヤーを順につなげてモデルを構成します。ここでは、密な層、ドロップアウト層、そして出力層が定義されています。

ランダムに選択されたハイパーパラメーターを使用して、モデルをコンパイルします。損失関数、オプティマイザー、およびメトリックを定義します。

構築されたモデルを返します。

input_shape が5で、n_classes が2であるモデルを作成し、 model 変数に代入します。

この関数は、ランダムに選択されたハイパーパラメーターを使用して、機械学習モデルを作成するため、異なるハイパーパラメーターを使って何度も実行することで、最適なモデルを見つけることができます。



## ハイパーパラメーターについて

ハイパーパラメーターは、機械学習モデルの設定に関するパラメーターのことです。これらのパラメーターは、モデルの振る舞いに大きな影響を与えるため、モデルの性能を改善することができます。

例えば、密な層のユニット数や学習率、ドロップアウト率などがハイパーパラメーターの一例です。これらのパラメーターを変更することにより、モデルの精度や速度を向上させることができます。

しかし、適切なハイパーパラメーターの設定は非常に難しく、最適な設定を見つけるためには、何度も試行錯誤する必要があります。そのため、ハイパーパラメーターのチューニングは、機械学習の重要な課題の一つとなっています。