human
Can you provide a code to 5 given the following:
5.6.3 Softmax-with-Lossレイヤ
出力層であるソフトマックス関数について考える。ソフトマックス関数は入力された値を正規化して出力する(出力の和が1になる)。
ニューラルネットワークにおける推論ではソフトマックス関数は不要(Affineレイヤの出力のうち最も高い値(スコア)を推論値とすれば良いので)だが、学習時には必要になる。
ここでは損失関数である交差エントロピー誤差(cross entoropy error)も含めて「Softmax-with-Loss レイヤ」という名前で実装する。
このレイヤはSoftmaxレイヤを通した後にCross Emtropy Errorレイヤを通す構造になっている。
順伝播ではSoftmaxレイヤの出力と教師データのラベルがCross Emtropy Errorレイヤの入力となり、損失Lを出力する。
逆伝播ではSoftmaxレイヤからは$(y_{1}-t_{1}, y_{2}-t_{2}, y_{3}-t_{3})$というシンプルな形で流れてくる。これにより、誤った推論を行った場合は大きな誤差が逆伝播されるが、正解している場合は小さい誤差が伝搬される。
このようにシンプルな形で流せるのはソフトマックス関数の損失関数として交差エントロピー誤差を選んでいるからである。(回帰問題における出力層に恒等関数、損失関数として2乗和誤差を用いることも同様(3.5参照))"
Please write code following the instructions in jupyter notebook style.
assistant
#Here is code to 5.

def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    
    return y

def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

class SoftmaxWithLoss:
    def __init__(self):
        self.loss = None
        self.y = None # softmaxの出力
        self.t = None # 教師データ

    def forward(self, x, t):
        self.t = t
        self.y = softmax(x)
        self.loss = cross_entropy_error(self.y, self.t)
        
        return self.loss

    def backward(self, dout=1):
        batch_size = self.t.shape[0]
        # データ1個あたりの誤差を全データに伝播させる
        dx = (self.y - self.t) / batch_size
       
        return dx