human
Can you provide a the Python program you requested given the following:
4.5 学習アルゴリズムの実装
ニューラルネットワークの学習手順のおさらい
前提
ニューラルネットワークは重みとバイアスが有り、訓練データに適応するように調整することを「学習」という。  

ステップ1(ミニバッチ)
訓練データからランダムに一部データ(ミニバッチ)を選び出す。ミニバッチの損失関数の値を減らすことを目的とする。

ステップ2(勾配の算出)
ミニバッチの損失関数を減らすために、各重みの勾配を算出する。

ステップ3(パラメータの更新)
重みパラメータを勾配方向にわずかだけ更新する。

ステップ4(繰り返す)
ステップ1,ステップ2、ステップ3を繰り返す。

ここではミニバッチとして無作為に選ばれたデータを使用していることから、「確率的勾配降下法(stochastic gradient descent。略してSGD)」と呼ばれる。
4.5.1 2層ニューラルネットワークのクラス
2層のニューラルネットワーク(隠れ層が1層)を一つのクラスとして実装する。
初期値はガウス分布に従う乱数で設定している。
numerical_gradientでは数値微分によって勾配を求めているが時間がかかる。後述する誤差逆伝播法をもちいたgradientも先に実装しておく。
assistant
#Here is the Python program you requested.
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
from src.functions import *
from src.gradient import numerical_gradient

class TwoLayerNet:

    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
    
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y
        
    # x:入力データ, t:教師データ
    def loss(self, x, t):
        y = self.predict(x)
        
        return cross_entropy_error(y, t)
    
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
        
    # x:入力データ, t:教師データ
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        
        grads = {}
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        
        return grads
        
    def gradient(self, x, t):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        grads = {}
        
        batch_num = x.shape[0]
        
        # forward
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        # backward
        dy = (y - t) /...