1 關於機器學習
機器學習是實現人工智能的手段, 其主要研究內容是如何利用數據或經驗進行學習, 改善具體算法的性能
多領域交叉, 涉及概率論、統計學, 算法復雜度理論等多門學科
廣泛應用於網絡搜索、垃圾郵件過濾、推薦系統、廣告投放、信用評價、欺詐檢測、股票交易和醫療診斷等應用
機器學習的分類
監督學習 (Supervised Learning)
從給定的數據集中學習出一個函數, 當新的數據到來時, 可以根據這個函數預測結果, 訓練集通常由人工標注
無監督學習 (Unsupervised Learning)
相較於監督學習, 沒有人工標注
強化學習(Reinforcement Learning,增強學習)
通過觀察通過什么樣的動作獲得最好的回報, 每個動作都會對環境有所影響, 學習對象通過觀察周圍的環境進行判斷
半監督學習(Semi-supervised Learning)
介於監督學習和無監督學習
深度學習 (Deep Learning)
利用深層網絡神經模型, 抽象數據表示特征
在Python中使用Scikit-learn(簡化為sklearn)這一模塊來處理機器學習
主要是依賴於numpy, scipy和matplotlib庫
開源可復用
sklearn中機器學習模型十分豐富, 需要根據問題的類型來選擇適當的模型
sklearn常用的函數
關於sklearn庫
sklearn是scikit-learn的簡稱,是一個基於Python的第三方模塊。sklearn庫集成了一些常用的機器學習方法,在進行機器學習任務時,並不需要實現算法,只需要簡單的調用sklearn庫中提供的模塊就能完成大多數的機器學習任務。
安裝sklearn庫需要安裝numpy, scipy(sklearn的基礎, 集成了多種數學算法和函數), matplotlib(數據繪圖工具)
注意安裝有順序: numpy -> scipy -> matplotlib -> sklearn
2 sklearn庫中的標准數據集及基本功能
2.1 標准數據集
1) 波士頓房價數據集
波士頓房價數據集包含506組數據,每條數據包含房屋以及房屋周圍的詳細信息。其中包括城鎮犯罪率、一氧化氮濃度、住宅平均房間數、到中心區域的加距離以及自住房平均房價等。因此,波士頓房價數據集能夠應用到回歸問題上。
加載數據集
sklearn.datasets.load_boston()
其中有參數return_X_y, 設置為True是會返回(data, target)兩個數據, 默認為False, 只返回data(包含了data和target兩個部分的內容)
具體使用
2) 鳶尾花數據集
鳶尾花數據集采集的是鳶尾花的測量數據以及其所屬的類別
測量數據包括: 萼片長度、萼片寬度、花瓣長度、花瓣寬度
類別共分為三類: Iris Setosa,Iris Versicolour,Iris Virginica, 該數據集可用於多分類問題
加載數據集
sklearn.datasets. load_iris()
同樣有參數return_X_y, 使用方法雷同
具體實例
3) 手寫數字數據集
手寫數字數據集包括1797個0-9的手寫數字數據,每個數字由8*8大小的矩陣構成,矩陣中值的范圍是0-16,代表顏色的深度。
加載數據集
sklearn.datasets.load_digits()
return_X_y: 效果依舊, True返回(data, target), 默認False直接返回全部內容
n_class: 設置數據類別, 返回數據的類別比設置類別低的數據樣本, 設置為5就會返回0~4的數據
基本使用
2.2 sklearn庫的基本功能
sklearn庫的共分為6大部分,分別用於完成分類任務、回歸任務、聚類任務、降維任務、 模型選擇以及數據的預處理
1) 分類任務
2) 回歸任務
3) 聚類任務
4) 降維任務
3 關於無監督學習
無監督學習的目標
利用無標簽的數據學習數據的分布或數據與數據之間的關系被稱作無監督學習
有監督學習和無監督學習的最大區別在於數據是否有標簽
無監督學習最常應用的場景是聚類(clustering)和降維(DimensionReduction)
聚類
聚類(clustering),就是根據數據的“相似性”將數據分為多類的過程
評估兩個不同樣本之間的“相似性” ,通常使用的方法就是計算兩個樣本之間的“距離”。使用不同的方法計算樣本間的距離會關系到聚類結果的好壞
1) 歐氏距離
歐氏距離是最常用的一種距離度量方法,源於歐式空間中兩點的距離。
計算公式
直觀表示
2) 曼哈頓距離
曼哈頓距離也稱作“城市街區距離”,類似於在城市之中駕車行駛,從一個十字路口到另外一個十字樓口的距離(x與y兩個方向的距離之和)
計算公式
直觀表示
3) 馬氏距離
馬氏距離表示數據的協方差距離,是一種尺度無關的度量方式。也就是說馬氏距離會先將樣本點的各個屬性標准化,再計算樣本間的距離。
計算公式, 其中s是協方差矩陣
馬氏空間的距離
4) 夾角余弦
余弦相似度用向量空間中兩個向量夾角的余弦值作為衡量兩個樣本差異的大小。余弦值越接近1,說明兩個向量夾角越接近0度,表明兩個向量越相似
計算公式
二維空間顯示
sklearn提供的常用聚類算法函數包含在sklearn.cluster這個模塊中
以同樣的數據集應用於不同的算法,可能會得到不同的結果,算法所耗費的時間也不盡相同,這是由算法的特性決定的
sklearn.cluster
sklearn.cluster模塊提供的各聚類算法函數可以使用不同的數據形式作為輸入
標准數據輸入格式:[樣本個數,特征個數]定義的矩陣形式
相似性矩陣輸入格式:即由[樣本數目,樣本數目]定義的矩陣形式,矩陣中的每一個元素為兩個樣本的相似度,如DBSCAN,AffinityPropagation(近鄰傳播算法)接受這種輸入。如果以余弦相似度為例,則對角線元素全為1. 矩陣中每個元素的取值范圍為[0,1]
具有代表性的聚類函數
降維
降維就是在保證數據所具有的代表性特征或分布的情況下, 將高維數據轉化為低維數據的過程
作用:
數據可視化
作為中間過程, 起到精簡數據, 提高其他機器學習算法效率的作用
分類和降維
聚類和分類都是無監督學習的典型任務,任務之間存在關聯,比如某些高緯數據的分類可以通過降維處理更好的獲得,另外學界研究也表明代表性的分類算法如k-means與降維算法如NMF之間存在等價性
sklearn和降維
降維是機器學習領域的一個重要研究內容,有很多被工業界和學術界接受的典型算法,截止到目前sklearn庫提供7種降維算法
降維過程也可以被理解為對數據集的組成成份進行分解(decomposition)的過程,因此sklearn為降維模塊命名為decomposition, 在對降維算法調用需要使用sklearn.decomposition模塊
sklearn.decomposition的常用算法
4 K-means方法及應用
k-means算法也就是k均值算法
k-means算法以k為參數,把n個對象分成k個簇, 使簇內具有較高的相似度, 而簇間的相似度較低
處理結果如下
1 隨機選擇k個點作為初始的聚類中心;
2 對於剩下的點,根據其與聚類中心的距離,將其歸入最近的簇
3 對每個簇,計算所有點的均值作為新的聚類中心
4 重復2、 3直到聚類中心不再發生改變
k-meams方法的處理過程如下
創建k-means實例
創建實例
sklearn.cluster.Kmeans()
n_clusters: 用於指定聚類中心的個數, 一般設定此參數, 別的參數使用默認值
init: 初始聚類中心的初始化方法, 默認值是k-means++
max_iter: 最大的跌打次數, 默認值是30
創建實例后, 可以通過實例對象調用fit_predict()計算簇中心以及為簇分配序號
其中會傳入參數data, 用於傳入需要加載的數據
返回的結果是一個label, 是聚類后各個數據所屬的標簽
k-means實例還有一個參數 cluster_centers_, 可以通過處理該參數的值來得到更進一步的處理數據
k-means的應用
處理中國1999年各省份的消費水平
處理的技術路線: sklearn.cluster.Kmeans
數據模型為
具體實例代碼如下
import numpy as np from sklearn.cluster import KMeans def loadData(filePath): fr = open(filePath,'r+') lines = fr.readlines() retData = [] retCityName = [] for line in lines: items = line.strip().split(",") retCityName.append(items[0]) retData.append([float(items[i]) for i in range(1,len(items))]) return retData,retCityName if __name__ == '__main__': data,cityName = loadData('31省市居民家庭消費水平-city.txt') km = KMeans(n_clusters=4) label = km.fit_predict(data) expenses = np.sum(km.cluster_centers_,axis=1) #print(expenses) CityCluster = [[],[],[],[]] for i in range(len(cityName)): CityCluster[label[i]].append(cityName[i]) for i in range(len(CityCluster)): print("Expenses:%.2f" % expenses[i]) print(CityCluster[i])
程序結果
深入程序解釋
label是一個列表類型, 具體的值是 對應的數據被分成哪一類的索引
也就是說, 遍歷cityname的時候同步取得label的值, 就可以對應的把城市名字放到合適的分類中, 這就是下面這句話的來源
CityCluster[label[i]].append(cityName[i])
生成的cluster_centers_是一個二維數據, 是一個列表里面套列表, 里面列表存儲的是一個分類中, 每個城市的值對應處理得到的結果
所以對這個值在1維上相加得到的就是每一個聚類的綜合的值, 這就是這句話的來源
expenses = np.sum(km.cluster_centers_,axis=1)
深入k-means
k-means在計算兩條數據相似性時, 默認是使用歐式距離, 且沒有給對應的參數來修改這個默認的計算距離的方法
如果需要修改這個默認的距離方式, 需要修改源代碼
源碼位置為C:\Python36\Lib\site-packages\sklearn\metrics\pairwise.py
162行的euclidean_distances()函數
建議使用scipy.spatial.distance.cdist方法
5 DBSCAN方法及應用
DBSCAN算法是一種基於密度的聚類算法
DBSCAN算法聚類的時候不要預先指定簇的個數
因而最終的簇的個數不確定
DBSCAN算法將數據點分為三類
核心點: 在半徑Eps內含有超過MinPts數據的點
邊界點: 在半徑Eps內點的數量小於MinPts, 但是落在核心點的鄰域內
噪音點: 既不是核心點也不是邊界點的點
DBSCAN的算法流程
1.將所有點標記為核心點、邊界點或噪聲點;
2.刪除噪聲點;
3.為距離在Eps之內的所有核心點之間賦予一條邊;
4.每組連通的核心點形成一個簇;
5.將每個邊界點指派到一個與之關聯的核心點的簇中(哪一個核心點的半徑范圍之內)
獲得密度聚類的實例
設Eps=3, MinPts=3, 采用曼哈頓距離聚類
處理核心點, 邊界點, 噪聲點
將不超過Eps=3的點相互圈起來形成一個簇, 核心點鄰域內的點都會被加入到這個簇當中
創建DBSCAN的實例
使用代碼
sklearn.cluster.DBSCAN()
其中有幾個參數
eps: 兩個樣本被看做鄰居節點的最大距離
min_samples: 簇的樣本數
metric: 距離的計算方式
創建完畢DBSCAN的對象之后
可以后 DBSCAN對象.fix(數據) 來生成一個結果, 這個結果有一個屬性是labels_
這個就是我們需要的標簽
其中標簽中值為-1表示噪聲
實例處理, 學生上網時間分布
數據
分別是 記錄編號, 學生編號, MAC地址, IP地址, 開始上網時間, 結束上網時間, 上網時長(秒), ...
具體代碼
import numpy as np import sklearn.cluster as skc from sklearn import metrics import matplotlib.pyplot as plt onlinetimes = {} with open("學生月上網時間分布-TestData.txt", encoding="utf8") as f: for line in f: info_list = line.strip().split(',') mac = info_list[2] onlinetime = int(info_list[6]) # 獲取上網的起始時候的小時 "2014-07-21 08:14:29.287000000" 這個的08 starttime = int(info_list[4].split(' ')[1].split(':')[0]) onlinetimes[mac] = (starttime, onlinetime) real_X = np.array([onlinetimes[key] for key in onlinetimes]).reshape((-1, 2)) # 只獲取上網的時間點 X = real_X[:, 0:1] db = skc.DBSCAN(eps=0.01, min_samples=20).fit(X) labels = db.labels_ # 獲得噪聲點比例 raito = len(labels[labels[:] == -1]) / len(labels) print('Noise raito:', format(raito, '.2%')) # 顯示算法性能 n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) print('Estimated number of clusters: %d' % n_clusters_) print("Silhouette Coefficient: %0.3f" % metrics.silhouette_score(X, labels)) for i in range(n_clusters_): print('Cluster ', i, ':') print(list(X[labels == i].flatten())) plt.hist(X, 24) plt.show()
實驗結果
處理數據的技巧
如果原始數據不協調, 不利於數據處理, 可以對原始數據進行無損變化來使得數據大小更加合適處理
具體的處理辦法就是取對數變換
6 PCA方法及其應用
PCA(Principal Component Analysis), 主成分分析, 是最常用的一種降維方法, 通常用於高維數據集的探索與可視化, 還可以用作數據壓縮和預處理等
PCA可以把具有相關性的高維變量合成為線性無關的低維變量,稱為主成分。主成分能夠盡可能保留原始數據的信息
相關術語
1) 方差
是各個樣本和樣本均值的差的平方和的均值,用來度量一組數據的分散程度
公式
2) 協方差
用於度量兩個變量之間的線性相關性程度,若兩個變量的協方差為0,則可認為二者線性無關。協方差矩陣則是由變量的協方差值構成的矩陣(對稱陣)
公式
3) 特征向量
矩陣的特征向量是描述數據集結構的非零向量
公式
主成分分析的原理
矩陣的主成分就是其協方差矩陣對應的特征向量,按照對應的特征值大小進行排序,最大的特征值就是第一主成分,其次是第二主成分,以此類推
使用PCA
創建PCA對象
sklearn.decomposition.PCA()
主要有兩個參數
n_components: 指定主要成分的個數
svd_solver: 設置特征值分解的方法, 默認為auto, 其他可選的還有full, arpack, randomized
創建PCA對象之后, 可以通過調用fit_transform(data)函數傳入需要降維的數據, 返回的數據就是降維之后處理完畢的數據
實例, 處理鳶尾花數據集
鳶尾花數據集是(150, 4)
可以利用PCA將數據集處理成(150, 2)的數據
處理鳶尾花數據讓其從4維數據編程2位平面數據, 具體代碼如下
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
data = load_iris()
y = data.target
X = data.data
pca = PCA(n_components=2)
reduced_X = pca.fit_transform(X)
red_x, red_y = [], []
blue_x, blue_y = [], []
green_x, green_y = [], []
for i in range(len(reduced_X)):
if y[i] == 0:
red_x.append(reduced_X[i][0])
red_y.append(reduced_X[i][1])
elif y[i] == 1:
blue_x.append(reduced_X[i][0])
blue_y.append(reduced_X[i][1])
else:
green_x.append(reduced_X[i][0])
green_y.append(reduced_X[i][1])
plt.scatter(red_x, red_y, c='r', marker='x')
plt.scatter(blue_x, blue_y, c='b', marker='D')
plt.scatter(green_x, green_y, c='g', marker='.')
plt.show()
具體結果
7 NMF方法及其實例
NMF(Non-negative Matrix Factorization, 非負矩陣分解), 是在矩陣中所有元素均為非負數約束條件之下的矩陣分解方法
基本思想:給定一個非負矩陣V,NMF能夠找到一個非負矩陣W和一個非負矩陣H,使得矩陣W和H的乘積近似等於矩陣V中的值
W矩陣:基礎圖像矩陣, 相當於從原矩陣V中抽取出來的特征
H矩陣:系數矩陣
NMF能夠廣泛應用於圖像分析、文本挖掘和語音處理等領域
矩陣分解優化目標: 最小化W矩陣H矩陣的乘積和原始矩陣之間的差別,目標函數如下
基於KL散度的優化目標, 損失函數如下
在sklearn庫中,可以使用sklearn.decomposition.NMF加載NMF算法,主要參數有
生成NMF對象
sklearn.decomposition.NMF()
n_components:用於指定分解后矩陣的單個維度k
init:W矩陣和H矩陣的初始化方式,默認為‘ nndsvdar’
使用NMF對人臉數據進行特征提取
使用 NMF對象.fit(數據) 來處理數據, 生成的內容還是在NMF對象中
獲取處理數據 NMF對象.components_ 獲取得到的數據
具體使用PCA和NMF處理人臉數據並且對比展示的代碼如下
from numpy.random import RandomState
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_olivetti_faces
from sklearn import decomposition
n_row, n_col = 2, 3
n_components = n_row * n_col
image_shape = (64, 64)
# Load faces data
dataset = fetch_olivetti_faces(shuffle=True, random_state=RandomState(0))
faces = dataset.data
def plot_gallery(title, images, n_col=n_col, n_row=n_row):
plt.figure(figsize=(2. * n_col, 2.26 * n_row))
plt.suptitle(title, size=16)
for i, comp in enumerate(images):
plt.subplot(n_row, n_col, i + 1)
vmax = max(comp.max(), -comp.min())
plt.imshow(comp.reshape(image_shape), cmap=plt.cm.gray,
interpolation='nearest', vmin=-vmax, vmax=vmax)
plt.xticks(())
plt.yticks(())
plt.subplots_adjust(0.01, 0.05, 0.99, 0.94, 0.04, 0.)
plot_gallery("First centered Olivetti faces", faces[:n_components])
estimators = [
('Eigenfaces - PCA using randomized SVD',
decomposition.PCA(n_components=6,whiten=True)),
('Non-negative components - NMF',
decomposition.NMF(n_components=6, init='nndsvda', tol=5e-3))
]
for name, estimator in estimators:
print("Extracting the top %d %s..." % (n_components, name))
print(faces.shape)
estimator.fit(faces)
components_ = estimator.components_
plot_gallery(name, components_[:n_components])
plt.show()
8 基於聚類的“圖像分割"
圖像分割:利用圖像的灰度、顏色、紋理、形狀等特征,把圖像分成若干個互不重疊的區域,並使這些特征在同一區域內呈現相似性,在不同的區域之間存在明顯的差異性。 然后就可以將分割的圖像中具有獨特性質的區域提取出來用於不同的研究
圖像分割技術已在實際生活中得到廣泛的應用。例如:在機車檢驗領域,可以應用到輪轂裂紋圖像的分割,及時發現裂紋,保證行車安全;在生物醫學工程方面,對肝臟CT圖像進行分割,為臨床治療和病理學研究提供幫助
圖像分割常用方法:
1 閾值分割:對圖像灰度值進行度量,設置不同類別的閾值,達到分割的目的
2 邊緣分割:對圖像邊緣進行檢測,即檢測圖像中灰度值發生跳變的地方,則為一片區域的邊緣
3 直方圖法:對圖像的顏色建立直方圖,而直方圖的波峰波谷能夠表示一塊區域的顏色值的范圍,來達到分割的目的
4 特定理論:基於聚類分析、小波變換等理論完成圖像分割
實例描述
目標: 利用K-means聚類算法對圖像像素點顏色進行聚類實現簡單的圖像分割
輸出: 同一聚類中的點使用相同顏色標記,不同聚類顏色不同
技術路線: sklearn.cluster.KMeans
具體代碼
import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
def loadData(filePath):
f = open(filePath,'rb')
data = []
img = image.open(f)
m,n = img.size
for i in range(m):
for j in range(n):
x,y,z = img.getpixel((i,j))
data.append([x/256.0,y/256.0,z/256.0])
f.close()
return np.mat(data),m,n
imgData,row,col = loadData('kmeans/bull.jpg')
label = KMeans(n_clusters=4).fit_predict(imgData)
label = label.reshape([row,col])
pic_new = image.new("L", (row, col))
for i in range(row):
for j in range(col):
pic_new.putpixel((i,j), int(256/(label[i][j]+1)))
pic_new.save("result-bull-4.jpg", "JPEG")