一、 異常檢查
- 假設我們已經收集到了一些數據集,並希望利用這些數據形成一個模型P,當我們輸入測試樣本x_test,這個模型能夠幫我們判斷這個樣本是否爲異常數據(數據分佈如下圖所示)。
1 參數估計
-
概念:給定不帶標籤的數據集,來近似的估計出正態分佈的期望值與方差。
-
期望:每個特徵的期望可以通過求每個特徵的均值來獲得。
-
方差:通過樣本與期望之差的平方除以樣本總數來估計方差。
(注:這同時也稱爲μ與σ的極大似然估計)
2 異常檢測程序
- 選擇能夠表現出異常樣本的特徵
- 利用參數估計,計算出期望和方差
- 然後給定一個新樣本,來計算樣本的密度
- 看密度是否小於閥值來判斷該樣本是否爲異常值
- 假設我們有一些樣本,每個樣本具有兩個特徵值x_1,x_2。從下方的三維圖中可以比較直觀的看出,粉色圈之外的P都是密度比較低的,也就是說這些點出現的概率是比較小的。那麼當出現這些點時,就要注意這是否爲異常值了。
3 異常檢測分組
- 假設我們有10000個正常的樣本,20個異常樣本。將這些樣本分爲訓練集(6000個好樣本),交叉驗證集(2000個好樣本,10個異常樣本)和測試集(2000個好樣本,10個異常樣本)。
- 然後使用訓練集計算出一個模型。接着用交叉驗證集和測試集來測試y=0/1的數量。
- 最後利用準確性和召回來計算F值。(注:通過使用不同的閥值來獲取最大的F值)
4 何時用異常檢測和監督學習?
-
異常檢測:當我們的正樣本數量很少時,我們很難讓我們的算法從正樣本當中學習到一定的規律,並且異常出現的情況可能也有很大的不同。
-
監督學習:我們有足夠多的正樣本,因此我們的算法能夠從這些樣本中學習到一定的規律,從而進行預測。
5 誤差分析思想
- 首先檢驗異常樣本,觀察異常樣本當中是否存在某些規律,然後重新創建一個新的特徵值。
比如說我的四個特徵值當中,經常出現CPU很高,但是網絡流量比較低,那麼這個時候就可以創建一個新的特徵值用(CPU2)或(CPU)/網絡流量。
6 多變量異常檢測
-
多元高斯分佈密度公式
-
Σ的第一行第一列是x1的方差,第二行第二列是x2的方差。當方差變小是,坡度就會變陡,當方差變大時,坡度就會變大,如下圖所示。
-
測試相關性
如果改變協方差,就會得到不同的高斯分佈,下圖可看到,x與y時一起增加的。
如果將協方差變爲負數,還會出現同樣趨勢的話,那麼這個時候我們就可以看出,x1與x2是呈現除負相關的。
7 代碼實戰:
- 讀取數據
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
from scipy.io import loadmat
os.chdir('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex8-anomaly detection and recommendation/data/')
data = loadmat('ex8data1.mat')
data
數據如下:
- 查看分佈
X = data['X']
fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1],s=50)
plt.show()
分佈情況如下:
- 參數估計每個特徵值的期望和方差,並利用參數擬合模型,計算訓練集每個數據的概率密度函數
from scipy import stats
def compute(X):
"""計算期望值與方差
Params:
X:訓練集數據
return:
X1_mean,X1_sigma,X2_mean,X2_sigma"""
m = X.shape[0]
X1 = X[:,0]
X2 = X[:,1]
X1_mean = X1.mean()
X2_mean = X2.mean()
X1_sigma = np.power(X1-X1_mean,2).mean()
X2_sigma = np.power(X2-X2_mean,2).mean()
return X1_mean,X1_sigma,X2_mean,X2_sigma
if __name__ == '__main__':
X1_mean,X1_sigma,X2_mean,X2_sigma=compute(X)
p = np.zeros((X.shape[0],X.shape[1]))
p[:,0] = stats.norm(X1_mean,X1_sigma).pdf(X[:,0])
p[:,1] = stats.norm(X2_mean,X2_sigma).pdf(X[:,1])
p.shape
結果如下:
- 利用訓練好的模型計算交叉訓練集每個樣本的概率密度
def val_pd(Xval,X1_mean,X1_sigma,X2_mean,X2_sigma):
"""利用訓練好的模型來計算交叉驗證集的概率密度
Param:
Xval:交叉驗證集數據"""
p_val = np.zeros((Xval.shape[0],Xval.shape[1]))
p_val[:,0] = stats.norm(X1_mean,X1_sigma).pdf(Xval[:,0])
p_val[:,1] = stats.norm(X2_mean,X2_sigma).pdf(Xval[:,1])
return p_val
if __name__ == '__main__':
Xval = data['Xval']
yval = data['yval']
p_val = val_pd(Xval,X1_mean,X1_sigma,X2_mean,X2_sigma)
p_val.shape
結果如下:
- 尋找合適的閥值
def select_threshold(p_val,yval):
"""選擇最優閥值
Params:
p_val:運用訓練好的模型計算出來的交叉集的概率密度
yval:交叉集數據對應的真實標籤
return:
best_threshod:最終閥值
best_f1:最好的f值"""
best_threshod = 0
best_f1 = 0
f1 = 0
step = (p_val.max()-p_val.min())/1000
for epsilon in np.arange(p_val.min(),p_val.max(),step):
preds = p_val < epsilon
# np.logical_and(x1==1,x2==2) 檢查兩個narray在對應位置上的數據是否一致,默認返回bool型
tp = np.sum(np.logical_and(preds==1,yval==1)).astype(float)
fp = np.sum(np.logical_and(preds==1,yval==0)).astype(float)
fn = np.sum(np.logical_and(preds==0,yval==1)).astype(float)
prec = tp/(tp+fp)
rec = tp/(tp+fn)
f1 = (2*prec*rec)/(prec+rec)
if f1>best_f1:
best_f1 = f1
best_threshod = epsilon
return best_threshod,best_f1
if __name__ == "__main__":
best_threshod,best_f1 = select_threshold(p_val,yval)
best_threshod,best_f1
- 繪製出訓練集當中的異常點
outliners = np.where(p<best_threshod)
outliners
fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1])
ax.scatter(X[outliners[0],0],X[outliners[0],1],color='red')
plt.show()
結果如下:
二、 推薦系統
- 假設有四位用戶對3部愛情片和2部動作片分別進行了評分。其中每個用戶都有一部沒有給出評分,推薦系統就根據這些數據來推測用戶對這些未評分的電影會給出多少分。
- 其中:n_u表示用戶數量;n_m表示電影數量;r(i,j)=1表示第j位用戶已經對第i部電影進行了評分。y(i,j)表示第j位用戶給第i部的電影的評分
解決此類問題可以使用線性迴歸的思想,那麼我們的目標就是優化一個θ,來使的θ.T*x的值與實際值y(i,j)相近。公式如下:
1 協同過濾
- 選擇特徵
- 比如說我們已經知道了用戶對電影的評分(θ),我們要尋找一個特徵。
- 我們的優化目標就從θ轉到了優化x。
-
第一個式子的目標是優化θ,其中i:r(i,j)=1是指對該用戶評價過的電影求和
-
第二個式子的目標是優化x,其中j:r(i,j)=1是指對某一部電影對評價過它的用戶j求和
-
第三個式子的目標是同時優化θ和x,其中(i,j):r(i,j)=1是指對所有有分數的電影進行求和。
-
流程:
注:這裏不用加x0和θ0
2 矢量化計算
-
例子:通過用戶最佳瀏覽的商品來推測出用戶可能會購買的其他產品
-
紫色圈的數據表頁用戶1對於電影1的評分
3 均值歸一化
-
假設我們現在有了用戶5,並且用戶5對所有的電影都沒有給出評分。那麼當我們嘗試去優化θ(5)的時候,我們得到的θ(5)應該是[0,0],這樣我們的算法在預測用戶5對電影的評分是就都是0。
-
首先取前面四個用戶對每一部電影的評分均值,然後得出向量μ。用μ來作爲用戶5對每個電影的評分
4 代碼實戰
2 協同過濾
- 讀取數據,分析數據
文件當中包含的數據包括:Y:每個用戶對每一步電影的評分(每一列表示每一個用戶對所有電影的評分情況);R:每個用戶是否對某一步電影進行了評分(是=1,否=0)
data2 = loadmat('ex8_movies.mat')
Y = data2['Y']
R = data2['R']
Y.shape,R.shape
結果如下:
- 根據公式編寫代價函數
def cost(params,Y,R,features):
"""計算代價函數
Params:
params:存放X與Theta數據的narray
Y:電影數量*用戶數量的矩陣(包含了每一位用戶對所有電影的平分情況)
R:電影數量*用戶數量的矩陣(用1表示第i個用戶對第j部電影進行了評分)
features:特徵數量
return:
J:代價函數"""
Y= np.mat(Y)
R = np.mat(R)
num_movies,num_users = Y.shape
X = np.reshape(params[:num_movies*features],(num_movies,features)) #(1682,10)
Theta = np.reshape(params[num_movies*features:],(num_users,features)) #(943,10)
J = 0
error = np.multiply(X@Theta.T - Y,R) #(1628,943),乘R的原因在於計算評價過的電影的誤差
square_error = np.power(error,2)
J = (1/2) * np.sum(square_error)
return J
if __name__ == '__main__':
movies = 5
users = 4
features = 5
X_ = X[:movies,:features]
Theta_ = Theta[:users,:features]
Y_ = Y[:movies,:users]
R_ = R[:movies,:users]
params_ = np.concatenate((np.ravel(X_),np.ravel(Theta_)))
J = cost(params_,Y_,R_,features)
print(J)
結果如下:
- 編寫代替度函數的代價函數
def cost(params,Y,R,features):
"""計算代價函數
Params:
params:存放X與Theta數據的narray
Y:電影數量*用戶數量的矩陣(包含了每一位用戶對所有電影的平分情況)
R:電影數量*用戶數量的矩陣(用1表示第i個用戶對第j部電影進行了評分)
features:特徵數量
return:
J:代價函數
grad:包含X與Theta梯度函數的narray"""
Y= np.mat(Y)
R = np.mat(R)
num_movies,num_users = Y.shape
X = np.reshape(params[:num_movies*features],(num_movies,features)) #(1682,10)
Theta = np.reshape(params[num_movies*features:],(num_users,features)) #(943,10)
J = 0
X_grad = np.zeros((num_movies,features))
Theta_grad = np.zeros((num_users,features))
error = np.multiply(X@Theta.T - Y,R) #(1628,943),乘R的原因在於計算評價過的電影的誤差
square_error = np.power(error,2)
J = (1/2) * np.sum(square_error)
X_grad = error@Theta #(1682,10)
Theta_grad = error.T@X #(943,10)
grad = np.concatenate((np.ravel(X_grad),np.ravel(Theta_grad)))
return J,grad
- 編寫帶正則化的梯度函數
def reg_cost(params,Y,R,features,learning_rate):
"""計算代價函數
Params:
params:存放X與Theta數據的narray
Y:電影數量*用戶數量的矩陣(包含了每一位用戶對所有電影的平分情況)
R:電影數量*用戶數量的矩陣(用1表示第i個用戶對第j部電影進行了評分)
features:特徵數量
return:
J:代價函數"""
Y= np.mat(Y)
R = np.mat(R)
num_movies,num_users = Y.shape
X = np.reshape(params[:num_movies*features],(num_movies,features)) #(1682,10)
Theta = np.reshape(params[num_movies*features:],(num_users,features)) #(943,10)
J = 0
X_grad = np.zeros((num_movies,features))
Theta_grad = np.zeros((num_users,features))
error = np.multiply(X@Theta.T - Y,R) #(1628,943),乘R的原因在於計算評價過的電影的誤差
square_error = np.power(error,2)
J = (1/2) * np.sum(square_error)
J = J + (learning_rate/2)*np.sum(np.power(Theta,2))
J = J + (learning_rate/2)*np.sum(np.power(X,2))
X_grad = error@Theta + (learning_rate*X)#(1682,10)
Theta_grad = error.T@X + (learning_rate*Theta)#(943,10)
grad = np.concatenate((np.ravel(X_grad),np.ravel(Theta_grad)))
return J,grad
- 來給自己推薦電影,這裏運用練習中給出的數據,首先讀取文件,存儲到字典當中
with open('movie_ids.txt',encoding= 'gbk') as f:
movie_idx={}
for each_movie in f:
each_movie = each_movie.strip()
tokens = each_movie.split(' ',1)
movie_idx[int(tokens[0])-1] = tokens[1]
ratings = np.zeros((1682, 1)) #添加自己的一列
ratings[0] = 4
ratings[6] = 3
ratings[11] = 5
ratings[53] = 4
ratings[63] = 5
ratings[65] = 3
ratings[68] = 5
ratings[97] = 2
ratings[182] = 4
ratings[225] = 5
ratings[354] = 5
Y_add = np.append(Y,ratings,axis=1)
R_add = np.append(R,ratings!=0,axis=1)
movie_idx[0]
- 進行均值歸一化
步驟:計算每一部電影的評價分->用原來的電影評分-平均分->
movies_num =Y.shape[0]
user_num =Y.shape[1]
features =10
learning_rate = 10.
X_test = np.random.random(size=(movies_num*features)) #隨機初始化
Theta_test = np.random.random(size=(user_num*features))
params_test = np.concatenate((X_test.ravel(),Theta_test.ravel()))
# 均值歸一化
Ymean = np.zeros((Y.shape[0],1)) #初始化所有電影的評價得分
Ynorm = np.zeros((Y.shape[0],user_num))
m = Y.shape[0]
for i in range(m):
index = np.where(R[i,:]==1)[0]
Ymean[i] = Y[i,index].mean()
Ynorm[i,index] = Y[i,index]-Ymean[i]
Ynorm.mean()
- 訓練模型
from scipy.optimize import minimize
fmin = minimize(fun=reg_cost
,x0=params_test
,args=(Ynorm,R_add,features,learning_rate)
,method = 'CG', jac = True,options={'maxiter':100})
fmin
協同優化
- 推薦電影
X = np.reshape(fmin.x[:movies_num*features],(movies_num,features))
Theta = np.reshape(fmin.x[movies_num*features:],(user_num,features))
predictions = X@Theta.T #所有的預測值
my_pred = predictions[:,-1].reshape(Ymean.shape[0],1) + Ymean #預測我自己的電影偏好
#獲取喜歡電影前十部的索引
inx = np.argsort(my_pred,axis=0)[::-1]
count = 1
for i in range(10):
movie_name = movie_idx[int(inx[i,:])]
print('Top {} movies U might like:{}'.format(count,movie_name))
count+=1
三、大數據算法
1 隨機梯度下降
-
如果當我們的數據集有10000000條數據,那麼這個計算量就會非常的大,此時如果再去使用梯度下降,我們會耗費過多的計算力。大數據算法就是用來解決這個問題的。
-
Stochastic梯度下降算法的思想是首先,隨機打亂數據,然後每一次迭代只要擬合一個訓練樣本即可。其中cost函數發生了變化。
-
隨機梯度下降是迂迴前進的,最後會在全局最優的周圍徘徊。
2 Mini-batch 梯度下降
-
Mini-batch梯度下降就是每次迭代計算b個樣本。
-
在使用隨機梯度下降時,由於我們的θ優化走的是一條迂迴的路線,因此我們有可能有時會錯失獲取最佳θ的機會。面對這個問題,我們可以每迭代1000次就計算一次代價函數,有助於我們選擇最好的θ
- 在繪製代價函數時可能會遇到以下四種情況:
- 通過讓α變小,我們可以獲得紅色的折線
- 第二幅圖顯示了,如果我們每5000個樣本計算一次代價函數值,那麼我們就會獲得一個相對平滑的曲線
- 第三幅圖顯示了,我們如果每1000個樣本計算一次代價函數值可能不會得到這麼好的效果,應加大數量
- 第四幅圖顯示了,α過大出現的情況
四、在線學習算法
-
從時候的數據流當中進行學習
-
例子:比如你擁有一個快遞網站,用戶訪問你的網站獲取將其包裹從A地郵寄到B地的價格(x),然後決定是否郵寄(y)。在線學習算法就是每次一有用戶進來就優化一次θ,然後隨着用戶進來的越來越多,我們的模型會越來越適應消費者的需求。這種方法適用於用戶流比較大的網站。
1 Map-Reduce:
- 思想:將訓練集數據分成k份,分別傳給k個計算機進行計算,隨後彙總到一箇中心處理的計算機,來進行最後的處理,可以計算的非常的快速。
2 Photo OCR
-
Photo OCR又稱照片光學字符識別,目的是讓計算機提取圖片中的文字,然後通過輸入一些文字就可以找到目標照片
-
Pipeline
首先找到文字部分,然後切割識別,分類。
3 滑動窗口分類
- 例子:識別行人
- 首先給定訓練集,有行人和沒有行人,訓練出一個分類模型
2. 然後用一個矩形框去遍歷圖片的所有像素,然後找到行人。
- 例子:文字識別
-
首先給出正樣本和負樣本
-
然後用框去遍歷,下左白色部分是指程序認爲有文字的地方
- 然後再去放大白色區域部分,找到符合的部分
全部知識點
課上完啦!!!
參考資料: