本篇的筆記將結合前面三篇的筆記來闡述邏輯迴歸中應用到的技術和技巧,包括https://blog.csdn.net/chenleiyfk/article/details/87819794介紹的數據處理、激活函數和成本函數的使用技巧;https://blog.csdn.net/chenleiyfk/article/details/87926932介紹的梯度下降和https://blog.csdn.net/chenleiyfk/article/details/88032338介紹的前向傳播和反向傳播。
神經網絡的核心思維-特徵向量,69-80行的註釋已經介紹的很清楚了,特徵向量的維度是4,91行將維度降爲了2。92行是輸出結果的向量表示。這裏的表示和學習筆記中介紹到的轉置是一樣的,爲了編程和運算的便利,使用了轉置。109行對輸出結果的向量處理也是爲了編程和運算的便利。
還記得介紹邏輯迴歸符號慣例時說的麼?在符號上要注意的一點是當對神經網絡進行編程實現時經常會讓參數w和參數b分開用的技巧,定義一個額外的特徵稱並且使它等於1。這在113行體現了出來,記住這裏使用了轉置。表示(w^T) x+b的值的計算看下56行即可。
數據處理的總結,特徵向量的表示、編程和運算使用的轉置、特徵向量X與特徵權重W以及偏置b的計算實現,序列對應於69-80行、109行和113行、56行。
sigmoid函數-激活函數可見55-60行。損失函數只適用於單個訓練樣本,而代價函數是參數的總代價,可分別見48行和49行。
數據處理-激活函數-損失函數-代價函數大家順着看是否是計算圖的計算-前向傳播呢?可以自己順着上面介紹的行理一下代碼和這些個概念。
一個神經網絡的計算,都是按照前向或反向傳播過程組織的。首先計算出一個新的網絡的輸出(前向過程),緊接着進行一個反向傳輸操作。反向傳播見51行,結合37行,是不是改變一點點變量的值看一下優化對象的變化率,是不是在求導數呢?在結合36行是不是梯度下降的過程呢?
來一個大點的總結,35行的循環對compute_loss函數的調用,正着流程走前向傳播,返回反向傳播,反覆的迭代梯度下降。
至於初始化等其他的概念,大家自己看看代碼吧。下面附上邏輯迴歸展示的代碼。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
Created on 2019-02-26 10:10:35
sklearn_simple_LogisticRegression.py: sklearn做個簡單的示例。
邏輯迴歸
Input:
Output:
@author: clyfk
'''
# 你能留給歲月的,歲月能留給你的,除了一個更好的自己,別無其他。 #
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np
class logistic(object):
def __init__(self):
self.W = None
def train(self, X, y, learn_rate = 0.01, num_iters = 5000):
num_train,num_feature = X.shape
#init the weight
self.W = 0.001*np.random.randn(num_feature,1).reshape((-1,1))
loss = []
for i in range(num_iters):
error,dW = self.compute_loss(X,y)
self.W += -learn_rate*dW
loss.append(error)
if i%200==0:
print ('i=%d,error=%f' %(i,error))
return loss
def compute_loss(self,X,y):
num_train = X.shape[0]
h = self.output(X)
loss = -np.sum((y*np.log(h) + (1-y)*np.log((1-h)))) # 損失函數
loss = loss / num_train # 代價函數
dW = X.T.dot((h-y)) / num_train
return loss,dW
def output(self,X):
g = np.dot(X,self.W)
return self.sigmod(g)
def sigmod(self,X):
return 1/(1+np.exp(-X)) # sigmoid函數-激活函數
def predict(self,X_test):
h = self.output(X_test)
y_pred = np.where(h>=0.5,1,0)
return y_pred
"""
【IRIS數據集】
由Fisher在1936年整理,包含4個特徵
(Sepal.Length(花萼長度)、Sepal.Width(花萼寬度)、Petal.Length(花瓣長度)、Petal.Width(花瓣寬度)),
特徵值都爲正浮點數,單位爲釐米。
目標值爲鳶尾花的分類(Iris Setosa(山鳶尾)、Iris Versicolour(雜色鳶尾),Iris Virginica(維吉尼亞鳶尾))。
一共4個屬性,分3類。
與之相對,iris裏有兩個屬性iris.data,iris.target,
data裏是一個矩陣,一共4列,每一行代表某個被測量的鳶尾植物,一共採樣了150條記錄,iris.data.shape:(150, 4)
target是一個數組,存儲了data中每條記錄屬於哪一類鳶尾植物,所以數組的長度是150,數組元素的值因爲共有3類鳶尾植物,所以不同值只有3個。
"""
iris = load_iris()
data = iris.data
target = iris.target
"""
iris數據是可以展示多分類的示例,因此處是邏輯迴歸的學習
所以 截取了0、1目標值得數據
爲了方便二維平面的展示,只使用了2個特徵
"""
X = data[0:100,[0,2]] # 特徵向量的維度是2,轉置的表示
y = target[0:100]
print("data: ", X.shape)
print (X[:])
print("target: ", y.shape)
print (y[:])
plt.figure(1)
label = np.array(y)
index_0 = np.where(label==0)
plt.scatter(X[index_0,0], X[index_0,1], marker='x', color='b', label='0', s=15)
index_1 =np.where(label==1)
plt.scatter(X[index_1,0], X[index_1,1], marker='o', color='r', label='1', s=15)
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend(loc = 'upper left')
y = y.reshape((-1,1)) # 輸出結果的向量表示,轉置爲了編程和運算的便利
print("target: ", y.shape)
print (y[:])
one = np.ones((X.shape[0],1))
X_train = np.hstack((one,X)) # 在符號上要注意的一點是當對神經網絡進行編程實現時經常會讓參數w和參數b分開用的技巧,定義一個額外的特徵稱並且使它等於1
print("data: ", X_train.shape)
print (X_train[:])
#
BinaryClassification = logistic()
loss = BinaryClassification.train(X_train, y, 0.01, 10000)
print ("W: ", BinaryClassification.W.shape)
print (BinaryClassification.W)
#
x1 = np.arange(4,7.5,0.5)
x2_0 = ( - BinaryClassification.W[0] - BinaryClassification.W[1]*x1) / BinaryClassification.W[2]
x2_1 = (1- BinaryClassification.W[0] - BinaryClassification.W[1]*x1) / BinaryClassification.W[2]
plt.plot(x1, x2_0, color = 'blue')
plt.plot(x1, x2_1, color = 'red')
plt.figure(2)
plt.plot(loss)
plt.xlabel('Iteration number')
plt.ylabel('Loss value')
plt.show()