ニューラルネットワーク入門のLogistic回帰(分類問題)

23648 ワード

Logistic回帰(分類問題)
このチュートリアルでは、次の部分について説明します.
Logistic分類モデル前回のチュートリアルでは、入力と出力が1つしかない簡単なモデルを示しました.このチュートリアルでは、入力パラメータが2つの変数である2分類モデルを構築します.このモデルは統計的にLogistic回帰モデルと呼ばれ,ネットワーク構造は以下のように記述できる.
Logistic回帰モデル
まず、チュートリアルで使用するパッケージをインポートします.
import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.colors import colorConverter, ListedColormap
from matplotlib import cm

クラス分布の定義
チュートリアルでは、ターゲット分類tは、2つの独立した分布から生成され、t=1の場合、青色で表される.t=0の場合、赤色で表される.入力パラメータXN*2の行列であり、目標分類tN * 1のベクトルである.より直感的な表現は、下図を参照してください.
# Define and generate the samples
nb_of_samples_per_class = 20  # The number of sample in each class
red_mean = [-1,0]  # The mean of the red class
blue_mean = [1,0]  # The mean of the blue class
std_dev = 1.2  # standard deviation of both classes
# Generate samples from both classes
x_red = np.random.randn(nb_of_samples_per_class, 2) * std_dev + red_mean
x_blue = np.random.randn(nb_of_samples_per_class, 2) * std_dev + blue_mean

# Merge samples in set of input variables x, and corresponding set of output variables t
X = np.vstack((x_red, x_blue))
t = np.vstack((np.zeros((nb_of_samples_per_class,1)), np.ones((nb_of_samples_per_class,1))))
# Plot both classes on the x1, x2 plane
plt.plot(x_red[:,0], x_red[:,1], 'ro', label='class red')
plt.plot(x_blue[:,0], x_blue[:,1], 'bo', label='class blue')
plt.grid()
plt.legend(loc=2)
plt.xlabel('$x_1$', fontsize=15)
plt.ylabel('$x_2$', fontsize=15)
plt.axis([-4, 4, -4, 4])
plt.title('red vs. blue classes in the input space')
plt.show()

red vs. blue classes in the input space
Logistic関数とクロスエントロピー損失関数
Logistic関数
我々が設計したネットワークの目的は、入力されたxからターゲットtを予測することである.x = [x1, x2]、重みw = [w1, w2]、予測目標t = 1が入力されると仮定する.では、確率P(t = 1|x, w)は、ニューラルネットワーク出力のy、すなわちy = σ(x∗wT)である.ここで、σLogistic を表し、定義は以下の通りである.
Logistic関数
もし、Logistic関数とその導関数がまだはっきりしていない場合は、このチュートリアルを参照してください.詳しく説明しています.
クロスエントロピー損失関数
この分類問題の損失関数最適化については,各訓練サンプルiについて,交差エントロピー誤差関数を以下のように定義する交差エントロピー誤差関数を用いて解決した.
各サンプルiのクロスエントロピー誤差関数
訓練サンプル全体のクロスエントロピー誤差を計算するには、各サンプルの値を加算するだけでよい.
クロスエントロピー誤差関数
クロスエントロピー誤差関数の詳細については、このチュートリアルを参照してください.logistic(z)関数はLogistic関数,cost(y, t)関数は損失関数,nn(x, w)はニューラルネットワークの出力結果,nn_predict(x, w)はニューラルネットワークの予測結果を実現した.
# Define the logistic function
def logistic(z): 
    return 1 / (1 + np.exp(-z))

# Define the neural network function y = 1 / (1 + numpy.exp(-x*w))
def nn(x, w): 
    return logistic(x.dot(w.T))

# Define the neural network prediction function that only returns
#  1 or 0 depending on the predicted class
def nn_predict(x,w): 
    return np.around(nn(x,w))

# Define the cost function
def cost(y, t):
    return - np.sum(np.multiply(t, np.log(y)) + np.multiply((1-t), np.log(1-y)))
# Plot the cost in function of the weights
# Define a vector of weights for which we want to plot the cost
nb_of_ws = 100 # compute the cost nb_of_ws times in each dimension
ws1 = np.linspace(-5, 5, num=nb_of_ws) # weight 1
ws2 = np.linspace(-5, 5, num=nb_of_ws) # weight 2
ws_x, ws_y = np.meshgrid(ws1, ws2) # generate grid
cost_ws = np.zeros((nb_of_ws, nb_of_ws)) # initialize cost matrix
# Fill the cost matrix for each combination of weights
for i in range(nb_of_ws):
    for j in range(nb_of_ws):
        cost_ws[i,j] = cost(nn(X, np.asmatrix([ws_x[i,j], ws_y[i,j]])) , t)
# Plot the cost function surface
plt.contourf(ws_x, ws_y, cost_ws, 20, cmap=cm.pink)
cbar = plt.colorbar()
cbar.ax.set_ylabel('$\\xi$', fontsize=15)
plt.xlabel('$w_1$', fontsize=15)
plt.ylabel('$w_2$', fontsize=15)
plt.title('Cost function surface')
plt.grid()
plt.show()

Cost function surface
勾配降下最適化損失関数
勾配降下アルゴリズムの動作原理は、損失関数ξが各パラメータを導出し、次いで負の勾配方向に沿ってパラメータ更新を行うことである.
パラメータwは、一定の学習率に従って負の勾配方向に更新される、すなわちw(k+1)=w(k)−Δw(k+1)であり、Δwは、以下のように表すことができる.
Δw
各トレーニングサンプルi∂ξi/∂wについて、以下のように計算される.
損失関数のウェイトに対する導関数
ここで、yi=σ(zi)はニューロンのLogistic出力であり、zi=xi∗wTはニューロンの入力である.
損失関数の重みに対する導関数を詳細に導く前に,このチュートリアルでいくつかの導出を抽出した.
段階的に導く.
上記のステップの導出を参照すると、以下の詳細な導出を得ることができます.
詳細な導出
したがって、各重みについての更新Δwjは、
各ウェイトの更新
バッチ処理では、Nサンプルの勾配を加算する必要があります.すなわち、
バッチ更新
勾配降下アルゴリズムを開始する前に、パラメータにランダムな数値付与プロセスを行い、収束するまで勾配降下アルゴリズムを使用してパラメータを更新する必要があります.gradient(w, x, t)関数は、∂ξ/∂wdelta_w(w_k, x, t, learning_rate)関数の勾配を実現し、Δwを実現する.
# define the gradient function.
def gradient(w, x, t):
    return (nn(x, w) - t).T * x

# define the update function delta w which returns the 
#  delta w for each weight in a vector
def delta_w(w_k, x, t, learning_rate):
    return learning_rate * gradient(w_k, x, t)

勾配降下更新
訓練セットXの上で10回実行して予測を行い、下図には前の3回の結果が描かれており、図中の青い点はk回目、w(k)の値を示している.
# Set the initial weight parameter
w = np.asmatrix([-4, -2])
# Set the learning rate
learning_rate = 0.05

# Start the gradient descent updates and plot the iterations
nb_of_iterations = 10  # Number of gradient descent updates
w_iter = [w]  # List to store the weight values over the iterations
for i in range(nb_of_iterations):
    dw = delta_w(w, X, t, learning_rate)  # Get the delta w update
    w = w-dw  # Update the weights
    w_iter.append(w)  # Store the weights for plotting
# Plot the first weight updates on the error surface
# Plot the error surface
plt.contourf(ws_x, ws_y, cost_ws, 20, alpha=0.9, cmap=cm.pink)
cbar = plt.colorbar()
cbar.ax.set_ylabel('cost')

# Plot the updates
for i in range(1, 4): 
    w1 = w_iter[i-1]
    w2 = w_iter[i]
    # Plot the weight-cost value and the line that represents the update
    plt.plot(w1[0,0], w1[0,1], 'bo')  # Plot the weight cost value
    plt.plot([w1[0,0], w2[0,0]], [w1[0,1], w2[0,1]], 'b-')
    plt.text(w1[0,0]-0.2, w1[0,1]+0.4, '$w({})$'.format(i), color='b')
w1 = w_iter[3]  
# Plot the last weight
plt.plot(w1[0,0], w1[0,1], 'bo')
plt.text(w1[0,0]-0.2, w1[0,1]+0.4, '$w({})$'.format(4), color='b') 
# Show figure
plt.xlabel('$w_1$', fontsize=15)
plt.ylabel('$w_2$', fontsize=15)
plt.title('Gradient descent updates on cost surface')
plt.grid()
plt.show()

weight updates on the error surface
トレーニング結果の可視化
次のコードでは、トレーニングの結果を可視化します.
# Plot the resulting decision boundary
# Generate a grid over the input space to plot the color of the
#  classification at that grid point
nb_of_xs = 200
xs1 = np.linspace(-4, 4, num=nb_of_xs)
xs2 = np.linspace(-4, 4, num=nb_of_xs)
xx, yy = np.meshgrid(xs1, xs2) # create the grid
# Initialize and fill the classification plane
classification_plane = np.zeros((nb_of_xs, nb_of_xs))
for i in range(nb_of_xs):
    for j in range(nb_of_xs):
        classification_plane[i,j] = nn_predict(np.asmatrix([xx[i,j], yy[i,j]]) , w)
# Create a color map to show the classification colors of each grid point
cmap = ListedColormap([
        colorConverter.to_rgba('r', alpha=0.30),
        colorConverter.to_rgba('b', alpha=0.30)])

# Plot the classification plane with decision boundary and input samples
plt.contourf(xx, yy, classification_plane, cmap=cmap)
plt.plot(x_red[:,0], x_red[:,1], 'ro', label='target red')
plt.plot(x_blue[:,0], x_blue[:,1], 'bo', label='target blue')
plt.grid()
plt.legend(loc=2)
plt.xlabel('$x_1$', fontsize=15)
plt.ylabel('$x_2$', fontsize=15)
plt.title('red vs. blue classification boundary')
plt.show()

トレーニング結果の可視化