88383


入力されたxとyの値から0か1かを分類できるようにニューラルネットワークを学習させようとしているのですが、何度回してもうまく学習できません。  
どうすればよいのか教えていただけると幸いです。

[code]

    import numpy as np
    
    def sigmoid(x):
        return 1 / (1 + np.exp(-x)) 
    
    def sigmoid_grad(x):
        return (1.0 - sigmoid(x)) * sigmoid(x)
    
    def softmax(x):
        x = x - np.max(x, axis=-1, keepdims=True)   # オーバーフロー対策
        return np.exp(x) / np.sum(np.exp(x), axis=-1, keepdims=True)
    
    def cross_entropy_error(y, t):
        if y.ndim == 1:
            t = t.reshape(1, t.size)
            y = y.reshape(1, y.size)
            
        # 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
        if t.size == y.size:
            t = t.argmax(axis=1)
                 
        batch_size = y.shape[0]
        return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
    
    #予測を行う関数
    def predict(x,params):
            W1, W2 = params['W1'], params['W2']
            b1, b2 = params['b1'], 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(x,t,params):
        y = predict(x,params)
            
        return cross_entropy_error(y, t)
    
    #予測の精度を求める関数
    def accuracy(x,t,params):
            y = predict(x,params)
            y = np.argmax(y, axis=1)
            t = np.argmax(t, axis=1)
            
            accuracy = np.sum(y == t) / float(x.shape[0])
            return accuracy
    
    #勾配を求める関数
    def gradient(x,t,params):
            W1, W2 = params['W1'], params['W2']
            b1, b2 = params['b1'], 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)
            
            batch_num = x.shape[0]
    
            # backward
            dy = (y - t)/batch_num
            grads['W2'] = np.dot(z1.T, dy)
            grads['b2'] = np.sum(dy, axis=0)
            
            dz1 = np.dot(dy, W2.T)
            da1 = sigmoid_grad(a1) * dz1
            grads['W1'] = np.dot(x.T, da1)
            grads['b1'] = np.sum(da1, axis=0)
    
            return grads
    
    
    #重みとバイアスの初期化
    input_size=2 #入力層
    hidden_size=3 #中間層
    output_size=2 #出力層
    
    weight_init_std=0.1
    params = {}
    params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
    params['b1'] = weight_init_std * np.random.randn(hidden_size)
    params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
    params['b2'] = weight_init_std * np.random.randn(output_size)
    
    #データを分割
    f = open('2class.txt', 'r')
    datalist = f.readlines()
    
    num=1000
    learning_rate=0.01
    batch=100
    for i in range(num):
        #データ分割
        x=np.array([])
        t=np.array([])
        train_batch_mask = np.random.choice(2000, batch)
        for i in train_batch_mask:
            data=datalist[i].replace( '\n' , '' ).split(' ')
            x=np.append(x,[data[0],data[1]])
            t=np.append(t,[data[2],1-int(data[2])])
    
        x_test=x.reshape(batch,2).astype(float)
        t_test=t.reshape(batch,2).astype(float)
        
        grad=gradient(x_test,t_test,params)
        # 更新
        for key in ('W1', 'b1', 'W2', 'b2'):
            params[key] -= learning_rate * grad[key]
        inter=num*0.1
        if i % inter ==0:
            print(accuracy(x_test,t_test,params))
    
    f.close()
    
[/code]

2class.txt  
こちらは例でデータ数は2000個あります。

[code]

    0.07998 0.00000 0
    0.16921 0.00213 0
    0.07037 0.00177 0
    0.04757 0.00179 0
    0.12735 0.00641 0
    -0.14647 -0.14105 1
    -0.14371 -0.14192 1
    -0.13122 -0.13287 1
    -0.12394 -0.12870 1
    -0.11359 -0.12096 1
    -0.13076 -0.14280 1
    -0.13758 -0.15410 1
    
[/code]

結果

[code]

    0.51
    0.53
    0.62
    0.52
    0.58
    0.53
    0.52
    0.47
    
[/code]


CC BY-SA 4.0
2022-04-16T02:50:00.380
88352
2022-04-18T13:11:48.140
2022-04-16T06:15:24.500
3060
52245
question
python 機械学習 numpy 深層学習
二値分類問題をディープラーニングで解く際にうまく学習されない


結果を見るに、うまくできているのではないでしょうか？  
2値分類ｔの問題では、結果は0～1の間で出力されるのが普通で、0.5未満なら0、0.5以上なら1と判断します。。0～1の間になるのは、予測器の確度を表すためです。  
以下のようなコードで質問に貼られている結果を、0.5未満なら0、0.5以上なら1に置き換えてください。

[code]

    y_pred = np.where(y_pred_prob < 0.5, 0, 1)
    
[/code]

上手くできていない の意味を捉え違っていたらごめんなさい


CC BY-SA 4.0
2022-04-17T06:44:18.660
88366
2022-04-17T06:44:18.660
52255
88352
answer


単純にループ回数が不足してるんじゃないかと思います。  
2class.txt の内容にもよりますが `x + y > 0` のような単純なケースでも `num=10000` くらい必要で、 `x * y > 0`
だと `num=100000` くらい必要でした。

データ処理部分がPythonでのループになってて遅いので

[code]

    with open('2class.txt', 'r') as f:
        datalist = [list(map(float, l.split(' '))) for l in  f.readlines()]
        datalist = np.array(datalist)
    
[/code]

で予め配列にしておいて、次のようにnumpy操作だけにすると速くなります。

[code]

        train_batch_mask = np.random.choice(2000, batch)
        data = datalist[train_batch_mask]
        x_test = data[:,0:2]
        t = data[:,2]
        t_test = np.stack([t, 1-t], 1)
    
[/code]


CC BY-SA 4.0
2022-04-18T13:11:48.140
88383
2022-04-18T13:11:48.140
241
88352
answer