Logistic 多分類問題:
面對Logistic多分類問題,通常的分類是將一類單獨拎出來,然後其他剩下的分爲另一類。這樣就可以利用二元Logistic迴歸的思路了。
比如下圖,我們一共有三個類,那麼我們會有三個分類器,然後依此計算hypothesis函數的值,最後看那個類別下的h值最大,那麼就將其歸爲這一類。
過擬合問題:
簡單來說,過擬合就是指一個模型在訓練集上表現的相當好(代價函數可能非常的接近於0 ),但是在測試集上的表現比較差,無法準確的進行預測。
下圖中,圖1:可見一元的線性方程無法較好的去擬合這個房價的模型(因爲,房價在隨着大小的增加越來越趨向於穩定,但是這個模型擬合的線是沒有表現出來穩定的趨勢的。),因此我們可以叫這種現象爲“欠擬合(Under fitting)”或“高偏差(High bias)”; 圖3 可以看到是一個高階的模型,它擬合出來的線是由很多上下波動的,這可以叫“過度擬合(Over fitting)”或“高方程”.
解決:
- 減少特徵數量
- 正則化
概念:
通過懲罰模型中參數的方法來,使得模型變的平滑。
看下圖的這個例子。
原來的模型當中theta_3,theta_4分別是x的三次和x的四次的參數。因爲高階的存在,會使得我們的模型變得彎彎扭扭。那麼我們如果希望這個模型和左邊的那個相似應該怎麼做呢?
那必然是要減少theta_3和theta_4對於模型的影響!減少到theta_3和theta_4幾乎等於0(就好像被這兩項被去掉了一樣,這樣我們就可以得到一個近似左圖的模型了。)
那麼怎麼做呢?
我們可以在後面添加兩項,如下圖。
因爲我們期望這個代價函數得到最小值,那麼我們肯定不希望前面係數爲1000的theta_3和theta_4大,而是要這兩個參數儘可能的小,從而我們的theta_3,和theta_4對於整個模型的影響就會減小,使我們得到一個比較平滑模型。
上面的例子當中,我們知道想要懲罰哪一項,但是當我們的特徵數量非常多的時候,我們往往無法知道我們需要懲罰哪些特徵項。
因此,利用正則化來縮小出來theta_0外的所有的參數
這裏的lambda就是正則化參數,它是用來控制兩個目標的取捨的。
第一個目標:更好的擬合數據
第二個目標:使得參數儘可能的小
注:當lambda過大,可能就會對所有的參數懲罰過大,最後就的h函數可能就成爲下面這樣了。。
線性迴歸正則化:
- 梯度下降法:
我們將上面討論到的正則化方法加入到梯度下降函數當中,那麼我們求偏導之後的結果就如下圖所示。
其中alpha*(lamda/m)是一個很小很小的正數,所以說,每次更新一次參數,那麼我們的theta就會是原來的theta*比一小一點點的數,再減去後面的那項。
- 正規方程法:
在原來的基礎上增加一個lambda*一個對角矩陣(假設矩陣爲A,那麼A11就是0,對角線其他值都爲1)
對於不可逆問題:
利用正則化,只要保證lambda>0,那麼就可以使得矩陣可逆。
Logistic 迴歸正則化:
- 代價函數
- 梯度下降
Logistic迴歸 正則化實例:
- 首先讀取數據,查看數據分佈情況
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
Data.head(30)
sns.set(context='notebook',style='ticks',font_scale = 1.5)
sns.lmplot('exam1','exam2',hue = 'accepted',data=Data,height = 6,fit_reg=False,scatter_kws={'s':50})
plt.title('Regularized Logistic Regression')
plt.show()
結果如下:
從散點分佈情況來看,這個條決策線應當是一個近似圓形的線才能分割。
- 因爲目前讀取的數據最高只有一次項,所以要寫一個函數來進行轉化數據。
def feature_mapping(x,y,power,as_ndarray=False):
"""將函數轉化爲高階,把兩個特徵值轉化爲多個特徵值
polynomial expansion法"""
data = {'f{}{}'.format(i-p,p) : np.power(x,i-p)*np.power(y,p)
for i in np.arange(power+1)
for p in np.arange(i+1)}
if as_ndarray:
return np.array(pd.DataFrame(data))
else:
return pd.DataFrame(data)
x1 = np.array(Data['exam1'])
x2= np.array(Data['exam2'])
data = feature_mapping(x1,x2,power=6)
print(data.shape)
data.head()
注意根據兩個數值可以看出是幾次方:
f00:x10 * x20
f10: x11 * x20
f20: x12 * x20
所以根據輸入power值多少,就可以計算到幾次方,這樣就可以應用到我們的正則化當中的。
- 定義必要的函數:
def get_y(Data):
return np.array(Data.iloc[:,-1])
def sigmoid(z):
return 1/(1+np.exp(-z))
def gradient(theta,x,y):
return (1/len(x))* x.T@ (sigmoid(x@theta)-y)
def cost(theta, X, y):
return np.mean(-y * np.log(sigmoid(X @ theta)) - (1 - y) * np.log(1 - sigmoid(X @ theta)))
def regcost(theta,x,y,l=1):
m = len(x)
theta_j1_jn = theta[1:] #首先新建一個theta函數,因爲theta0不需要處理,所以取出theta1到n即可
regularized_term = (l/(2*m))* np.power(theta_j1_jn,2).sum() #根據公式計算出正則化項
return cost(theta,x,y)+regularized_term
def reg_descent(theta,x,y,l=1):
theta_j1_jn = theta[1:]
regularized_theta = (l/len(x))*theta_j1_jn #正則化項
regularized_term = np.concatenate([np.array([0]),regularized_theta]) #因爲theta_0不動,這時候要將其組合回去
return gradient(theta,x,y) + regularized_term
- 利用scipy.optimize的minimize來進行擬合
import scipy.optimize as ops
theta = np.zeros(data.shape[1])
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)
res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)
res
結果如下:
- 測試精確度
X = feature_mapping(x1,x2,power=6,as_ndarray=True)
y = get_y(Data)
res = ops.minimize(fun = regcost,x0 = theta,args=(X,y),method='Newton-CG',jac=reg_descent)
def pred_y(final_theta,x):
prob = sigmoid(x@final_theta)
test = []
for each in prob:
if each>0.5:
test.append(1)
else:
test.append(0)
return test
final_theta = res.x
pred = pred_y(final_theta,X)
print(classification_report(y,pred))
結果如下:
- 繪製決策邊界:
def feature_mapped_logistic_regression(power,l):
"""獲取最優擬合參數
Params:
power:函數最高次方
l:lambda
return:
final_theta:最優擬合參數"""
Data = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
x0 = np.array(Data['exam1'])
x1 = np.array(Data['exam2'])
y = get_y(Data)
X = feature_mapping(x0,x1,power,as_ndarray=True) #獲取高次方函數
theta = np.zeros(X.shape[1])
res = ops.minimize(fun=regcost,x0=theta,args=(X,y,l),method='TNC',jac=reg_descent)
final_theta = res.x
return final_theta
def find_decision_boundary(density, power, theta, threshhold):
""""找到最合適的參數
目前理解的不太清楚,希望知道的朋友可以留言告訴我一下,謝謝!"""
t1 = np.linspace(-1, 1.5, density) #因爲我數據點都是分佈在-1,1.5之間的,所以我取-1,1.5的等差數列密度爲1000個,爲了可以佈滿整個圖像
t2 = np.linspace(-1, 1.5, density)
cordinates = [(x, y) for x in t1 for y in t2] #取得各個點的座標
x_cord, y_cord = zip(*cordinates) #解壓
mapped_cord = feature_mapping(x_cord, y_cord, power) # 進行高次運算
inner_product = np.array(mapped_cord) @ theta
decision = mapped_cord[np.abs(inner_product) < threshhold] #增加條件
return decision.f10, decision.f01 #獲取x^1和y^1 用來畫邊界函數
def draw_boundury(power,l):
density =1000
threshhold= 2* 10**-3
final_theta = feature_mapped_logistic_regression(power,l)
x,y = find_decision_boundary(density, power, final_theta, threshhold)
dt = pd.read_csv('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex2-logistic regression/ex2data2.txt',names=['exam1','exam2','accepted'])
sns.lmplot('exam1','exam2',hue = 'accepted',data=dt,height=6,fit_reg=False,scatter_kws={'s':50})
plt.scatter(x,y,color='red',s=10)
plt.title('Desicion Boundary')
plt.show()
draw_boundury(power=6,l=1)
draw_boundury(power=6,l=0) #過擬合
draw_boundury(power=6,l=50) #欠擬合
結果:
lambda=1比較合適