Logistic Regression


論理回帰は,回帰により得られた結果を活性化関数により確率に変えるアルゴリズムである.
このとき用いた回帰に関する概念を次の文章でまとめた.線形回帰とは?
ロジス関数は独立変数(−inf,inf)=>(0,1)の確率で置き換えられ,この場合に知るべき概念はOzzとLogitである.

  • メリット
    オズは事件が発生する確率を事件が発生しない確率に分けた.
    確率=P(イベント発生)/P(イベント発生x)

  • ローグ
    名前からも分かるように、ロジーはオーズに日記を書いた.
    logを使用するのは、出力時に入力値の範囲([0,1]-確率のため、0-1の範囲値を持つ)を(-IF,INF)に変更するためです.
    logit = log(odds)

  • 論理関数(sigmoid)
    依存変数が1に属する確率をローグの逆関数で表す.
    logistic = ex/1+exe^{x}/1+e^{x}ex/1+ex
  • 一般に,深さ学習や機械学習ではロジャーズ関数(sigmoid)で得られる確率の閾値を0.5に設定し,閾値を超えると1または0を返す.
    このときのloss値は次のようになります.(y:label,h(x):回帰)
    loss function = -y*log(h(x)) - (1-y)*log(1-h(x))
    簡単に言えば、ロギス回帰をサブプログラムで実現しましょう.
    # import
    import numpy as np
    import matplotlib.pyplot as plt
    import tensorflow as tf
    
    # data
    np.random.seed(2022)
    x1 = np.random.randint(1,10, size=10)
    x2 = np.random.randint(1,5, size=(10))
    
    plt.scatter(x1,x2)

    入力値x dataの分布を上図に示します.このとき,y軸の値を2として分類する.
    x_data = np.array([x1,x2]).T
    y_data = [[1] if i>2 else [0] for i in x2]
    
    all_data = np.hstack([x_data,y_data])
    plt.scatter(all_data[:,:-2], all_data[:,-2:-1], c=all_data[:, 2])

    2以上であれば黄色が足りなければ紫色と確認できます.
    では、学習を通じて、上図に従って分類しましょう.
    # dataset
    dataset = tf.data.Dataset.from_tensor_slices((x_data, y_data)).batch(len(x_data))
    
    # weight & bias
    W = tf.Variable(tf.random.normal([2,1]))
    b = tf.Variable(tf.random.normal([1]))
    
    # loss function
    def loss_fn(x, y):
      hypothesis = tf.math.sigmoid(tf.matmul(x,W) + b)
      loss = -y * tf.math.log(hypothesis) - (1-y) * tf.math.log(1-hypothesis)
      loss = tf.reduce_mean(loss)
      return loss
    
    # gradients
    def grad(x, y):
      with tf.GradientTape() as tape:
        loss = loss_fn(x,y)
        return tape.gradient(loss, [W,b])
    
    # optimizer
    optimizer = tf.keras.optimizers.SGD(learning_rate=3e-2) # Adam이나 다른 옵티마이저도 사용 가능
    
    epochs = 2000
    lr = 1e-3
    
    for epoch in range(1, epochs+1):
      for x, y in dataset:
        grads = grad(x,y)
        optimizer.apply_gradients(grads_and_vars=zip(grads, [W,b]))  
        if epoch % 200 == 0:
          print("Epoch : {:2}, Loss : {:4f}".format(epoch, loss_fn(x,y)))
        

    全部で2000回勉強しましたが、このモデルは『科学』に適しているはずです.しかし今回はテストデータなしで分類できるかどうかだけが注目されているので気になりません.
    # predict
    prediction = tf.cast(tf.sigmoid(tf.matmul(x_data,W)+b)>0.5, dtype=tf.float32)
    acc = tf.reduce_mean(tf.cast(tf.equal(prediction, y_data),dtype=tf.float32))
    print("Accuracy : {:.2f}%".format(acc*100))

    予測したy値と実値yが全て一致していることが確認できます.