\documentclass[a4paper]{bxjsarticle}  
\usepackage{zxjatype}
\usepackage[ipa]{zxjafont}
\usepackage{listings}
\usepackage{amsmath} 
\usepackage{graphicx} 

\title{深層学習DAY1}

%\date{\today}

\begin{document}
\maketitle

\section{ニューラルネットワーク}
\subsection{入力層から中間層}
最初の層を入力層(input layer),最後の層を出力層(output layer)といい,その間にある層は中間層 (intermediate layer)もしくは隠れ層 (hidden layer) という.
よくある構造は入力層,中間層,出力層から成る,3層の構造(アーキテクチャ)である.また複数の中間層を持たせれば、さらに多層のニューラルネットワークとすることができる.

\subsection{確認テスト}
\subsubsection{数式をpythonで書く}
\begin{lstlisting}[language=python]
u1 = np.dot(x,w) + b
\end{lstlisting}

\subsubsection{中間層の出力を定義しているコード}
\begin{lstlisting}[language=python]
z = functions.sigmoid(u)
\end{lstlisting}

\subsection{活性化関数}
ニューラルネットワークにおいて、次の層への出力の大きさを決める非線形の関数であり,入力値の値によって,次の層への信号のON/OFFや強弱を定める働きを持つ.
中間層の活性化関数を以下に示す.
\subsubsection{ステップ関数}
値を超えたら発火する関数であり,出力は常に1か0である.0から1間の間を表現できず線形分離可能なものしか学習できないことが課題である.
\begin{lstlisting}[language=python]
def step_function(x):
    if x > 0:
        return 1
    else:
        return 0
\end{lstlisting}

\subsubsection{シグモイド関数}
0から1の間を緩やかに変化する関数である一方で,大きな値では出力の変化が微小なため,勾配消失問題を引き起こすことが課題である.
\begin{lstlisting}[language=python]
def sigmoid(x):
    return 1/(1 + np.exp(-x))
\end{lstlisting}

\subsubsection{ReLU関数}
今最も使われている活性化関数であり,勾配消失問題の回避とスパース化に貢献
\begin{lstlisting}[language=python]
def relu(x):
    return np.maximum(0, x)
\end{lstlisting}

\subsubsection{全結合層}
活性化関数を示すコード
\begin{lstlisting}[language=python]
z1 = functions.sigmoid(u)
\end{lstlisting}

\subsection{出力層}
出力層は信号の大きさはそのままに変換し,中間層はしきい値の前後で信号の強弱を調整する.また,分類問題の場合,出力層の出力は0から1の範囲に限定し,総和は1である.

\subsection{誤差関数}
正解データと予測データがどれだけ一致しているかを表す.
\subsection{確認テスト}
\subsubsection{誤差関数はなぜ引き算でなく2乗するのか}
正の値で表したいから

\subsubsection{誤差関数の1/2はどういう意味を持つか}
微分したときの係数を考慮したもの

\subsection{出力層の活性化関数}
ソフトマックス関数を用いて,3クラス以上の分類精度を確率で表す.

\subsection{確認テスト}
ソフトマックス関数に該当するコードを示す.
\begin{lstlisting}[language=python]
def softmax(x):
#ミニバッチとして取り扱う場合
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T

    x = x - np.max(x) # オーバーフロー対策

# 分母はK番目まですべての要素の値で分子はi番目の要素の値

    return np.exp(x) / np.sum(np.exp(x))     
\end{lstlisting}

クロスエントロピーに関するコードを示す.

\begin{lstlisting}[language=python]
# クロスエントロピー
def cross_entropy_error(d, y):

# 全て並べる

    if y.ndim == 1:
        d = d.reshape(1, d.size)
        y = y.reshape(1, y.size)
        
    # 教師データがone-hot-vectorの場合,正解ラベルのインデックスに変換
    if d.size == y.size:
        d = d.argmax(axis=1)
             
    batch_size = y.shape[0]

# 対数関数は0に落ちないように1e-7
# yは0,1が並んだもので正解は1
# dはこの場所が正解と選んだところ
    return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size
\end{lstlisting}

\subsection{勾配降下法}
重みパラメータを最適化する手法でコードは以下に示す.
\begin{lstlisting}[language=python]
network[key]  -= learning_rate * grad[key]

grad = backward(x, d, z1, y)
\end{lstlisting}

\subsubsection{学習率}
大きすぎると収束しない.小さすぎると収束までに時間がかかる.

\subsubsection{確率的勾配降下法}
データが冗長な場合の計算コストの軽減し,望まない局所極小解に収束するリスクの軽減が可能.

\subsubsection{オンライン学習とは何か}
学習データが入ってくるたびに都度パラメータを更新し,学習を進めていく方法.一方バッチ学習では一度にすべての学習データを使ってパラメータ更新を行う.

\subsubsection{ミニバッチ勾配降下法}
ランダムに分割したデータの集合に属するサンプルの平均誤差

SGDのメリットを損なわず,計算機の計算資源を有効利用できる→CPUを利用したスレッド並列化やGPUを利用したSIMD並列化

\subsubsection{数値微分のデメリット}
各パラメータそれぞれについて計算することが多く,順伝搬の計算を繰り返し行う必要があり負荷が大きく誤差逆伝播法を利用する.

\subsection{誤差逆伝播法}
算出された誤差を、出力層側から順に微分し、前の層前の層へと伝播し,最小限の計算で各パラメータでの微分値を解析的に計算する手法.偏微分を用いる.

\subsection{確認テスト}
誤差逆伝播では不要な再帰的処理を避けることが出来る.既に行った計算結果を保持しているソースコードを抽出せよ.

\begin{lstlisting}[language=python]
# 出力層でのデルタ
    delta2 = functions.d_mean_squared_error(d, y)
# b2の勾配
    grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
    grad['W2'] = np.dot(z1.T, delta2)
# 中間層でのデルタ
    #delta1 = np.dot(delta2, W2.T) * functions.d_relu(z1)

## 試してみよう
    delta1 = np.dot(delta2, W2.T) * functions.d_sigmoid(z1)

    delta1 = delta1[np.newaxis, :]
# b1の勾配
    grad['b1'] = np.sum(delta1, axis=0)
    x = x[np.newaxis, :]
# W1の勾配
    grad['W1'] = np.dot(x.T, delta1)
\end{lstlisting}

空欄のコードを探せ

\begin{lstlisting}[language=python]
# 出力層でのデルタ
    delta2 = functions.d_mean_squared_error(d, y)

# W2の勾配
    grad['W2'] = np.dot(z1.T, delta2)
\end{lstlisting}
\end{document}