我們之前討討論過回歸在機器學習及統計領域裡佔有極其重要的角色,之前我們用scikit-learn 套件學習過回歸,這單元再度來討論回歸,但改用 tf 套件來處理。後續的單元中會碰到各種不同的 Loss function (誤失函數),這單元一開始先來探討幾種常見的 loss function。
🔶 Loss function (誤失函數)
是用量測真正的值和預測值之間的差,有時又稱cost function (成本函數),任何可以用來量測空間兩點間的不同的函數都可以做為誤失函數,一般要求是若是同一點則函數值為0,若而當兩點分得愈開函數值要變大。
■ Norm (範數)
之前已有討論過,這是最常用的度量之一,常用來表示距離。Norm 的定義是 $$ \left \| \textbf{x}\right \| _p =\left ( \sum_i^n \left | x_i \right | ^p \right )^{1/p}$$ 其中$p\geq 1$ 為一實數, 此定義稱 $l_p\mbox{-norm}$。當$p=1$ 時又稱 taxicab norm,$p=2$ 又稱 Euclidean norm,也是我們平時所說的歐氏距離,當$p$趨近於 $\infty$則是稱為infinity norm or maximum norm,定義成 $$\left \| \textbf{x}\right \| _\infty:= \max_i \left | x_i \right |$$ 常見的三種norm在 $\mathbb{R}^2$ 中 norm 為1的集合如下圖
![]() |
norm 為1的集合 |
import matplotlib.pyplot as plt import tensorflow as tf sess = tf.Session() x_vals = tf.linspace(-1., 1., 500) target = tf.constant(0.) l2_y_vals = tf.square(target - x_vals) l2_y_out = sess.run(l2_y_vals) l1_y_vals = tf.abs(target - x_vals) l1_y_out = sess.run(l1_y_vals) x_array = sess.run(x_vals) plt.plot(x_array, l2_y_out, 'b-', label='l2 Norm') plt.plot(x_array, l1_y_out, 'r--', label='l1 Norm') plt.grid(True) plt.ylim(-0.1, 0.4) plt.legend(loc='lower right', prop={'size': 11}) plt.show()
![]() |
L1, L2 Norm |
MSE 為$l_2$-norm 的延伸應用,計算$n$ 對$l_2$-norm 的平方再取平均,定義成
$${\textrm {MSE}} = \frac{1}{n}\sum_{i=1}^{n}\left (y_i-\hat {y}_i \right )^2$$
其中$y_i$ 為真正的值而$\hat {y}_i $預測的值。MSE 為最基本的度量之一。這個度量有時分母的$n$會用2取代,用以消掉當微分時2階項所產生的2,如此可化簡神經元誤差後向傳播調整係數的計算。
■ Hinge loss function
此函數通常被用於最大邊界(maximum margin)演算法,而最大邊界又是SVM(支撐向量機)用到的重要演算法,此函數定義成 $$L= \max ({0, 1-y \cdot \hat y})$$ 其中$y \in {\{-1, +1}\}$, $\hat y \in \mathbb{R}$, 此函數的輸出當$y$和 $\hat y$同號,且$|\hat y|\geq 1$時為0。
■ Cross entropy loss (相互熵)定義成
$$L=-y\cdot \log_2 {\hat y}-y\cdot \log_2 {(1-\hat y)}$$ 其中$y$ 和 $\hat y$都是介於 $0\sim 1$.
■ Sigmoid cross entropy loss (S 函數相互熵)$$L=-y\cdot \log_2 {f(\hat y)}-y\cdot \log_2 {(1-f(\hat y))}$$
其中$f(\cdot)$ 為Sigmoid function.
🔶 使用反矩陣公式求回歸
我們在單元05 多重回歸中己討論過鮮公式直接求解,在此回顧一下,如果以一個特徵對一個目標為例(亦即在$x-y$平面求解),可將所有的$n$個實例寫成
$y_0=\beta _0+\beta _1x_{0}$
$y_1=\beta _0+\beta _1x_{1}$
$\cdots$
$y_{n-1}=\beta _0+\beta _1x_{n-1}$
進一用矩陣表示成■ Hinge loss function
此函數通常被用於最大邊界(maximum margin)演算法,而最大邊界又是SVM(支撐向量機)用到的重要演算法,此函數定義成 $$L= \max ({0, 1-y \cdot \hat y})$$ 其中$y \in {\{-1, +1}\}$, $\hat y \in \mathbb{R}$, 此函數的輸出當$y$和 $\hat y$同號,且$|\hat y|\geq 1$時為0。
import matplotlib.pyplot as plt import matplotlib import tensorflow as tf sess = tf.InteractiveSession() %matplotlib inline myfont = matplotlib.font_manager.FontProperties( fname=r'C:/Windows/Fonts/msjh.ttf') target2 = tf.constant(-1.) target = tf.constant(1.) x_vals = tf.linspace(-3., 3., 500) hinge_y_vals = tf.maximum(0., 1. - tf.multiply(target, x_vals)) hinge_y_vals2 = tf.maximum(0., 1. - tf.multiply(target2, x_vals)) hinge_y_out = hinge_y_vals.eval() hinge_y_out2 = hinge_y_vals2.eval() x_array = x_vals.eval() plt.plot(x_array, hinge_y_out, 'b-', label='y=1') plt.plot(x_array, hinge_y_out2, 'r-', label='y=-1') plt.ylim(-1.5, 3) plt.legend(loc='lower right', prop={'size': 12}) plt.ylabel('輸出',fontproperties=myfont, size=14) plt.xlabel('預測 y 值',fontproperties=myfont, size=14) plt.grid() sess.close()
![]() |
Hinge loss function |
$$L=-y\cdot \log_2 {\hat y}-y\cdot \log_2 {(1-\hat y)}$$ 其中$y$ 和 $\hat y$都是介於 $0\sim 1$.
import matplotlib.pyplot as plt import matplotlib import tensorflow as tf sess = tf.InteractiveSession() %matplotlib inline x_vals = tf.linspace(-1., 2., 500) target = tf.constant(1.) target2 = tf.constant(0.5) xentropy_y_vals = - tf.multiply(target, tf.log(x_vals))-tf.multiply((1. - target), tf.log(1. - x_vals)) xentropy_y_vals2 = - tf.multiply(target2, tf.log(x_vals))-tf.multiply((1. - target2), tf.log(1. - x_vals)) xentropy_y_out = xentropy_y_vals.eval() xentropy_y_out2 = xentropy_y_vals2.eval() x_array =x_vals.eval() plt.plot(x_array, xentropy_y_out, 'b-', label='y=1') plt.plot(x_array, xentropy_y_out2, 'r-', label='y=0.5') plt.ylim(-1.5, 3) plt.legend(loc='lower right', prop={'size': 12}) plt.ylabel('L',size=14) plt.xlabel('$\hat y$',size=14) plt.grid() sess.close()
![]() |
相互熵 |
🔶 使用反矩陣公式求回歸
我們在單元05 多重回歸中己討論過鮮公式直接求解,在此回顧一下,如果以一個特徵對一個目標為例(亦即在$x-y$平面求解),可將所有的$n$個實例寫成
$y_0=\beta _0+\beta _1x_{0}$
$y_1=\beta _0+\beta _1x_{1}$
$\cdots$
$y_{n-1}=\beta _0+\beta _1x_{n-1}$
$\textbf{Y}=\textbf{X}\boldsymbol\beta$
其中$\textbf{Y}$為如下的 $n\times 1$ 矩陣,
$\textbf{Y}=\begin{bmatrix} y_0 \\ y_1 \\ \vdots \\ y_{n-1} \end{bmatrix}$
而 $\textbf{X}$為如下的$n\times 2$ 矩陣,
$\textbf{X}=\begin{bmatrix} 1& x_0 \\ 1& x_1 \\ \vdots&\vdots \\ 1& x_{n-1} \end{bmatrix}$$\boldsymbol\beta$為下列簡單的 $2\times 1$ 矩陣,
$\boldsymbol\beta=\begin{bmatrix} \beta_0 \\ \beta_1 \end{bmatrix}$,
表示成矩陣後,$\boldsymbol\beta$ 可由下列求得
$\boldsymbol\beta = (\textbf{X}^T \textbf{X})^{-1}\textbf{X}^T\textbf{Y}$
之前我們曾用numpy解上式,下列程式則是用 tf 解
import matplotlib.pyplot as plt import numpy as np import tensorflow as tf np.random.seed(101) sess = tf.InteractiveSession() %matplotlib inline x_vals = np.linspace(0, 10, 50) y_vals = x_vals + np.random.normal(0, 1, 50) x_vals_column = np.transpose(np.matrix(x_vals)) ones_column = np.transpose(np.matrix(np.repeat(1, 50))) A = np.column_stack((ones_column,x_vals_column)) b = np.transpose(np.matrix(y_vals)) A_tensor = tf.constant(A) b_tensor = tf.constant(b) tA_A = tf.matmul(tf.transpose(A_tensor), A_tensor) tA_A_inv = tf.matrix_inverse(tA_A) product = tf.matmul(tA_A_inv, tf.transpose(A_tensor)) beta_val = tf.matmul(product, b_tensor) solution_eval = beta_val.eval() print(solution_eval) y_intercept = solution_eval[0] slope = solution_eval[1] print('slope: ',slope) print('y_intercept: ', y_intercept) best_fit = [] for i in x_vals: best_fit.append(slope*i+y_intercept) plt.plot(x_vals, y_vals, 'o', label='Data') plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=2) plt.legend(loc='lower right') plt.ylabel('y values',size=14) plt.xlabel('x value',size=14) sess.close()
![]() |
tf 回歸公式計算 |
🔶 使用Cholesky 分解求回歸
矩陣反轉的公式求解 $\boldsymbol\beta$ 當矩陣很大時,在數值的運算很沒有效率,較可行的方法是利用Cholesky 分解,將$\textbf{X}^T \textbf{X}$分解成一個下三角和一個上三角矩陣相乘,寫成
$\textbf{X}^T \textbf{X}= \textbf{L} \textbf{U}$
則解最佳係數的問題變成解
$\textbf{L} \textbf{U} \boldsymbol\beta = \textbf{X}^T\textbf{Y}$
可先令
$ \textbf{U} \boldsymbol\beta =\boldsymbol\alpha$
並解出
$\textbf{L}\boldsymbol\alpha = \textbf{X}^T\textbf{Y}$
中的的$\boldsymbol\alpha $,再將其值帶入$ \textbf{U} \boldsymbol\beta =\boldsymbol\alpha$中解出$\boldsymbol\beta$,如此可避開求反矩陣。
import matplotlib.pyplot as plt import numpy as np import tensorflow as tf np.random.seed(101) sess = tf.InteractiveSession() %matplotlib inline x_vals = np.linspace(0, 10, 50) y_vals = x_vals + np.random.normal(0, 1, 50) x_vals_column = np.transpose(np.matrix(x_vals)) ones_column = np.transpose(np.matrix(np.repeat(1, 50))) A = np.column_stack((ones_column,x_vals_column)) b = np.transpose(np.matrix(y_vals)) A_tensor = tf.constant(A) b_tensor = tf.constant(b) tA_A = tf.matmul(tf.transpose(A_tensor), A_tensor) L = tf.cholesky(tA_A) tA_b = tf.matmul(tf.transpose(A_tensor), b) alpha = tf.matrix_solve(L, tA_b) beta_val = tf.matrix_solve(tf.transpose(L), alpha) beta_val = tf.matmul(product, b_tensor) solution_eval = beta_val.eval() print(solution_eval) y_intercept = solution_eval[0] slope = solution_eval[1] print('slope: ',slope) print('y_intercept: ', y_intercept) best_fit = [] for i in x_vals: best_fit.append(slope*i+y_intercept) plt.plot(x_vals, y_vals, 'o', label='Data') plt.plot(x_vals, best_fit, 'r-', label='Best fit line', linewidth=2) plt.legend(loc='lower right') plt.ylabel('y values',size=14) plt.xlabel('x value',size=14) sess.close()因使用相同的seed,解出來的結果會和直接求反陣的結果相同。一點需注意的是第16行中傳回的只有下三角矩,將此矩陣轉置就是分解所需的上三角。
🔶 使用tf Optimizer (佳化器)求回歸
上面用反矩陣或矩陣分解的方式求回歸都是直接用數學運算求解,並沒有使用到機器學習中學習的特性。下面的例子我們要用學習的方法求解,先前我們用scikit-learn求解時的主要的步驟約略是
- 讀進或產生資料
- 產生Optimizer的實例
- 使用Optimizer的method fit()去調適參數
- 使用predict() method 去預測
- 最後求性能並檢視結果
- 讀進或產生資料
- 產生placeholder 變數用以饋入資料
- 建立系統的模型及定義lost (cost) function
- 產生Optimizer的實例
- 建立sess及啟始變數
- 訓練
- 預測
- 最後求性能並檢視結果
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt %matplotlib inline np.random.seed(101) learning_rate = 0.0001 training_epochs = 1000 x_train = np.linspace(1, 10, 50) y_train = x_train + np.random.normal(0, 1, 50) X = tf.placeholder("float") Y = tf.placeholder("float") w = tf.Variable(0.1) b = tf.Variable(0.1) y_model = tf.multiply(X, w) + b cost = tf.reduce_mean(tf.square(Y-y_model)) train_op = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) sess = tf.Session() init = tf.global_variables_initializer() sess.run(init) for epoch in range(training_epochs): for (x, y) in zip(x_train, y_train): sess.run(train_op, feed_dict={X: x, Y: y}) w_val = sess.run(w) b_val = sess.run(b) sess.close() y_learned = x_train*w_val+b_val print('w_val: ',w_val) print('b_val: ', b_val) plt.plot(x_train, y_train, 'o',label='Data') plt.plot(x_train, y_learned, 'r',label='Best fit line', linewidth=2) plt.legend(loc='lower right') plt.ylabel('y values',size=14) plt.xlabel('x value',size=14);
![]() |
Optimizer learning |
沒有留言:
張貼留言