機器學習 Machine Learning
- 1 基礎
- 2 基本概念
- 3 監督學習-分類
1 基礎
基礎知識(Basic Concepts)
訓練集,測試集,特徵值,監督學習,非監督學習,分類,迴歸
1.1 機器學習概念
- 多領域交叉學科,涉及概率論、統計學、逼近論、凸分析、算法複雜度等多門學科。
- 專門研究計算機怎樣模擬和實現人類的學習行爲,以獲取新的知識和技能,重新組織新的知識結構使之不斷改善自身的性能
1.2 學科定位
- 人工智能(Artificial Intelligence,AI)的核心,是使計算機具有智能的根本途徑,其應用遍及人工智能的各個領域,主要方法是歸納、綜合而不是演繹。
1.3 機器學習定義
- 探究和開發一系列算法來如何使計算機不需要通過外部明顯的指示,而可以自己通過數據來學習和建模,並且利用建好的模型和新的輸入來進行預測的學科。
- 一門不需要外部程序指示,而讓計算機有能力自我學習的學科。
- 機器學習是一門人工智能的科學,該領域的主要研究對象是人工智能,特別是如何在經驗學習中改善算法的性能。
- 機器學習是對能通過經驗自動改進的計算機算法的研究。
1.4 什麼是學習
- 針對經驗E(Experience)和一些列的任務T(Task)和一定表現的衡量P(performe),如果隨着經驗的積累,針對定義好的任務T可以提高表現P,說明計算機具有學習能力。
- 下棋、語音識別、自動駕駛、語言翻譯、計算機視覺、推薦系統、無人機、識別垃圾郵件、人臉識別、推薦系統
1.5 深度學習
- 深度學習是機器學習延伸出來的一個新領域,由以人腦結構爲啓發的神經網絡算法爲起源,加之模型結構的增加發展,並伴隨大數據和計算能力的提高而產生的一系列新的算法。
- 深度學習作爲機器學習中延伸出來的一個領域,被應用在圖像處理和計算機視覺,自然語言處理以及語音識別等領域。自2006年至今,學術界和工業界合作在深度學習方面的研究與應用取得了突破性的進展。以ImageNet爲數據庫的經典圖像中的物體識別競賽爲例,擊敗了所有傳統算法,取得了前所未有的精確度。
1.5 監督學習-分類
監督學習(Supervised Learning):分類(Classification)
- 決策樹(Decision Tree) ,銀行信用自動評估系統
- 鄰近取樣(Nearest Neighbor) ,人臉識別
- 支持向量機(Support Vector Machine) ,圖片中的紅眼檢測,結腸癌晚期分類
- 神經網絡算法(Neural Network),手寫數字識別,圖片分類
1.6 監督學習-迴歸
監督學習(Supervised Learning):迴歸(Regression)
- 線性迴歸(Linear Regression),銷量預測,價格預測
- 非線性迴歸(Non-linear Regression),銷售預測,價格預測
1.7 非監督學習
非監督學習(Unsupervised Learning)
- K-mean算法聚類(Clustering),人臉分類
- hierarchical dustering算法聚類,人臉噪音移除
1.8 機器學習步驟框架
- 把數據拆分爲訓練集和測試集
- 用訓練集和訓練集的特徵向量來訓練算法
- 用學習來的算法運用在測試集上來評估算法,可能要調整參數(parameter tuning),
2 基本概念
- 基本概念:訓練集、測試集、特徵值、監督學習、非監督學習、半監督學習、分類、迴歸
- 概念學習是指從有關某個布爾函數的輸入輸出樣例中推斷出該布爾函數。
- 概念定義在實例(Instance)集合之上,這個集合表示爲X。
- 待學習的概念或目標函數成爲目標概念(Target Concept),記作做C。
- 訓練集(training set / data)/ 訓練樣例(training examples):用來進行訓練,也就是生產模型,或者算法的數據集
- 測試集(testing set / data)/ 測試樣例(testing example):用來專門進行測試已學習好的模型或者算法的數據集
- 特徵向量(features/feature vector):屬性的集合,通常用一個向量來表示,附屬於一個實例
- 標記(label):C(x),實例類別的標記
- 正例:positive example
- 反例:negative example
- 分類(Classification):目標標記爲類別型數據(category)
- 迴歸(regression):目標標記爲連續性數值(Continuous Numeric Value)
- 有監督學習(supervised learning):訓練集有類別標記(Calss Label)
- 無監督學習(unsupervised learning):無類別標記(Class Label)
- 半監督學習(semi-supervised learning):有類別標記訓練集+無類別標記訓練集
3 監督學習-分類
監督學習(Superviesd Learning):分類(Classification)
3.1 決策樹
決策樹(Decision Tree)
3.1.1 機器學習中分類和預測算法的評估
- 準確率
- 速度
- 強壯性
- 可規模性
- 可解釋性
3.1.2 什麼是決策樹/判定樹?
- 判定樹是一個類似於流程圖的數結構,其中每個內部節點表示在一個屬性上的測試,每個分支代表一個屬性輸出,而每個樹葉節點代表類和類分佈。樹的最頂層是根節點。
3.1.2 熵(entropy)概念
- 信息和抽象如何度量?
- 1948年香農提出信息熵的概念
- 一條信息的信息量大小和他的不確定性有直接的關係
- 要搞清楚一件非常不確定的事情,或者是我們一無所知的事情,需要了解大量的信息
- 信息量的度量等於不確定性的多少
- 變量的不確定性越大,熵也越大
3.1.3 決策樹歸納算法(ID3)
信息獲取量(Information Gain):Gain(A)=Info(D)-Info_A(D).
通過A來作爲節點分類獲取了多少信息
- 樹以代表訓練樣本的單個節點開始(步驟1)
- 如果樣本都在同一個類,則該節點成爲樹葉,並用該類標號(步驟2和3)
- 否則,算法使用稱爲信息增益的基於熵的度量作爲啓發信息,選擇能夠最好的將樣本分類的屬性(步驟6).該屬性成爲該節點的“測試”或“判定”屬性(步驟7)
- 在算法的該版本中,所有的屬性都是分類的,即離散值。連續屬性必須離散化。
- 對測試屬性的每個已知的值,創建一個分支,並據從劃分樣本(步驟8-10)
- 算法使用同樣的過程,遞歸的形成每個劃分上的樣本的判定樹。一旦一個屬性出現在一個結點時,就不必該節點的任何後代上考慮它(步驟13)
- 遞歸劃分步驟劃分條件僅當下列條件之一停止。
- (a)給定結點的所有樣本屬於同一類(步驟2和3)
- (b)沒有剩餘屬性可以用來進一步劃分樣本(步驟4),在此情況下,使用多數表決(步驟5)
- 這涉及將給定結點轉換成樹葉,並用樣本中的多數所在的類標記它
3.1.4 樹葉剪枝(避免overfitting)
- 先剪枝
- 後剪枝
3.1.5 決策樹的優點
- 直觀
- 便於理解
- 小規模數據集有效
3.1.6 決策樹的缺點
- 處理連續變量不好
- 類別較多時,錯誤增加的較快
- 可規模性一般
3.1.7 代碼實現
Python 機器學習庫:scikit-learn
簡單高效的數據挖掘和機器學習庫
對所有用戶開放,根據不同需求,高度可重用性
基於Numpy、SciPy、matplotlib,開源
- 數據
RID,age,income,student,credit_rating,Class_buys_computer
1,youth,high,no,fair,no
2,youth,high,no,excellent,no
3,middle_aged,high,no,fair,yes
4,senior,medium,no,fair,yes
5,senior,low,yes,fair,yes
6,senior,low,yes,excellent,no
7,middle_aged,low,yes,excellent,yes
8,youth,medium,no,fair,no
9,youth,low,yes,fair,yes
10,senior,medium,yes,fair,yes
11,youth,medium,yes,excellent,yes
12,middle_aged,medium,no,excellent,yes
13,middle_aged,high,yes,fair,yes
14,senior,medium,no,excellent,no
- 代碼
from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import preprocessing
from sklearn import tree
from sklearn.externals.six import StringIO
allElectronicsData = open(r'D:\IDEA\ML\MachineLearningBasics\DataSets\AllElectronics.csv', 'rb')
reader = csv.reader(allElectronicsData)
headers = reader.next()
print 'headers'
print(headers)
featureList = []
labelList = []
for row in reader:
labelList.append(row[len(row) - 1])
rowDict = {}
for i in range(1, len(row) - 1):
rowDict[headers[i]] = row[i]
featureList.append(rowDict)
print 'featureList'
print(featureList)
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()
print("dummyX:" + str(dummyX))
print(vec.get_feature_names())
print("labelList:" + str(labelList))
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
print("dummyY:" + str(dummyY))
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf = clf.fit(dummyX, dummyY)
print('clf:' + str(clf))
with open("allElectronicInformationGainOri.dot", 'w') as f:
f = tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)
oneRowX = dummyX[0, :]
print('oneRowX:' + str(oneRowX))
newRowX = oneRowX
newRowX[0] = 1
newRowX[2] = 0
print('newRowX:' + str(newRowX))
# predictedY = clf.predict(newRowX)
# print('predictedY:' + str(predictedY))
- 結果
3.2 鄰近取樣
鄰近取樣(Nearest Neighbor)
3.2.1 最鄰近規則分類(K-Nearest Neighbor) KNN算法
Cover和Hart在1968年提出最初的鄰近算法
分類(Classification)算法
輸入基於實例的學習(instance-based learning),懶惰學習(Lazy Learning)
3.2.2 算法詳述
- 爲了判斷未知實例的類別,以所有已知類別的實例作爲參照
- 選擇參數K
- 計算未知實例與所有已知實例的距離
- 選擇最近K個已知實例
- 根據少數服從多數的投票法則(majority-voting),讓未知實例歸類爲K個最鄰近樣本中最多數的類別
3.2.3 關於距離衡量方法
- Euclidean Distance 定義
- 其他距離衡量:餘弦值(COS),相關度(correlation),曼哈頓距離(Manhattan Distance)
3.2.4 算法評價
- 優點:簡單,易於理解,容易實現,通過對K的選擇可具備丟噪音數據的健壯性
- 缺點:需要大量空間存儲所有已知實例,算法複雜度高(需要比較所有已知實例與要分類的實例)
- 當其樣本分佈不平衡時,比如其中一類樣本過大(實例數量過多)佔主導時,新的未知實例容易被歸類爲這個主導樣本,因爲這類樣本實例的數量過大,但這個新的未知實例並不接近目標樣本
3.2.5 KNN算法應用
最鄰近規則分類KNN(K-Nearest Neighbor)算法應用
- SKLearnExample.py
# Example of KNN implemented
from sklearn import neighbors
from sklearn import datasets
knn = neighbors.KNeighborsClassifier()
iris = datasets.load_iris()
print iris
knn.fit(iris.data, iris.target)
predictedLabel = knn.predict([[0.1, 0.2, 0.3, 0.4]])
print predictedLabel
3.2.6 Iris(虹膜)數據集介紹
- 150個實例
- sepal length:萼片長度,sepal width:萼片寬度,petal length:花瓣長度,petal width:花瓣寬度
- 類別:setosa,versicolor,virginica
3.2.7 代碼實現
# coding=utf-8
import csv
import random
import math
import operator
# filename 文件名稱
# split 分割
# trainingSet 訓練集
# testSet 測試集
def loadDataset(filename, split, trainingSet=[], testSet=[]):
with open(filename, 'rb') as csvFile:
lines = csv.reader(csvFile)
dataset = list(lines)
for x in range(len(dataset) - 1):
for y in range(4):
dataset[x][y] = float(dataset[x][y])
if random.random() < split:
trainingSet.append(dataset[x])
else:
testSet.append(dataset[x])
# instance1 第一個座標
# instance2 第二個座標
# length 維數
def euclideanDistance(instance1, instance2, length):
distance = 0
for x in range(length):
distance += pow((instance1[x] - instance2[x]), 2)
return math.sqrt(distance)
# 獲取K個最近的實例
def getNeighbors(trainingSet, testInstance, k):
distances = []
length = len(testInstance) - 1
for x in range(len(trainingSet)):
dist = euclideanDistance(testInstance, trainingSet[x], length)
distances.append((trainingSet[x], dist))
distances.sort(key=operator.itemgetter(1))
neighbors = []
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
def getResponse(neighbors):
class_votes = {}
for x in range(len(neighbors)):
response = neighbors[x][-1]
if response in class_votes:
class_votes[response] += 1
else:
class_votes[response] = 1
sorted_votes = sorted(class_votes.iteritems(), key=operator.itemgetter(1), reverse=True)
return sorted_votes[0][0]
# 獲取準確率
def getAccuracy(testSet, predictions):
correct = 0
for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct += 1
return (correct / float(len(testSet))) * 100.0
def main():
training_set = []
test_set = []
split = 0.67
loadDataset(r'D:\IDEA\ML\MachineLearningBasics\DataSets\iris.data.txt', split, training_set, test_set)
print 'Train Set:' + repr(len(training_set))
print 'Test Set:' + repr(len(test_set))
predictions = []
k = 3
for x in range(len(test_set)):
neighbors = getNeighbors(training_set, test_set[x], k)
result = getResponse(neighbors)
predictions.append(result)
print '>> predicted=' + repr(result) + ',actual=' + repr(test_set[x][-1])
accuracy = getAccuracy(test_set, predictions)
print 'Accuracy:' + repr(accuracy) + '%'
main()
3.3 支持向量機
支持向量機(Support Vector Machine,SVM)
3.3.1 原理簡介
- 最早於1963年被提出,深度學習出現之前(2012),SVM被認爲機器學習中近十年來,最成功、表現最好的算法。
- 機器學習的一般框架:訓練集,提取特徵向量, 結合一定的算法(分類器:比如決策樹,KNN),得到結果
- SVM尋找區分兩類的超平面(hyper plane),使邊際(margin)最大
- 總共可以有多少個超平面?無數個
- 如何選取邊際最大的超平面(Max Margin Hyper plane)?
- 超平面到一側最近點的距離等於到另一側最近點的距離,兩側的兩個超平面平行
- 線性可區分(linear separable)和線性不可區分(linear inseparable)
3.3.2 定義與公式建立
- 一般情況
超平面可定義爲:W * X + b = 0
W:Weight Vector,權重
W={w1,w2,w3,w4...wn}
n:特徵值的個數
X:訓練實例
b:bias,偏好
- 二維平面
假設二維特徵向量:x=(x1,x2)
把b想象成額外的weight
超平面的方程變爲:w0 + w1*x1 + w2*x2 = 0
超平面右上方的點滿足:w0 + w1*x1 + w2*x2 > 0
超平面左下方的點滿足:w0 + w1*x1 + w2*x2 < 0
- 所有坐落在邊際的兩邊的超平面上的向量被成爲支持向量(support vectors)
from sklearn import svm
x = [[2, 0], [1, 1], [2, 3]]
y = [0, 0, 1]
clf = svm.SVC(kernel='linear')
clf.fit(x, y)
print clf
# get support vectors
print clf.support_vectors_
# get indices of support vectors
print clf.support_
# get number of support vectors for each class
print clf.n_support_
3.3.3 SVM算法特性
- 訓練好的模型的算法複雜度是由支持向量的個數決定的,而不是由數據的維度決定的。所以SVM不容易產生Overfitting。
- SVM訓練出來的模型完全依賴於支持向量(Support Vector),即使訓練集裏面所有非支持向量被去除,重複訓練過程,結果依然會得到完全一樣的模型。
- 一個SVM如果訓練得出的支持向量個數比較少,SVM訓練出來的模型容易被泛化
3.3.4 線性不可分情況
- 數據集在空間中對應的向量不可被一個超平面區分
兩個步驟來解決
- 利用一個非線性的映射,把源數據集中的向量轉化到一個更高維度的空間
- 在這個高維度的空間中,找一個線性的超平面來根據線性可分的情況處理
- 如何選擇合理的非線性轉化把數據轉化到高維度?
- 如何解決計算內積時算法複雜度非常高的問題?
3.3.5 具體實現
print __doc__
import numpy as np
import pylab as pl
from sklearn import svm
# create 40 separable points
np.random.seed(0)
x = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
y = [0] * 20 + [1] * 20
# fit the model
clf = svm.SVC(kernel='linear')
clf.fit(x, y)
# get the separating hyper plane
w = clf.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (clf.intecept_[0]) / w[1]
# plot the parallels to the separating hyper plane the pass through the support vectors
b = clf.support_vectors_[0]
yy_down = a * xx + (b[1] - a * b[0])
b = clf.support_vectors[-1]
yy_up = a * xx + (b[1] - a * b[0])
print "w:", w
print "a:", a
print "support_vectors:", clf.support_vectors_
print "clf.coef_", clf.coef_
# plot the line,the points,and the nearest vectors the plane
pl.plot(xx, yy, 'k-')
pl.plot(xx, yy_down, 'k--')
pl.plot(xx, yy_up, 'k--')
pl.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=80, facecolor='none')
pl.scatter(x[:, 0], x[:, 1], c=y, cmap=pl.cm.Paired)
pl.axis('tight')
pl.show()
3.4 神經網絡算法
神經網絡算法(Neural Network)
3.4.1 算法詳述
-
背景:以人腦中的神經網絡爲啓發,歷史上出現多個不同的版本,最著名的算法是1980年的Back Propagation,被使用在多層向前神經網絡上
-
多層向前神經網絡Multilayer Feed-Forward Neural Network
-
多層向前神經網絡由以下部分組成:輸入層(Input Layer),隱藏層(hidden layer),輸入層()
-
每層由單元(units)組成
-
輸入層(Input Layer)是由訓練集的實例特徵向量傳入
-
經過連接點的權重(weight)傳入下一層,一層的輸出是另一層的輸入
-
隱藏層的個數可以是任意的,輸入層有一層,輸出層有一層
-
每個單元也可以被稱作神經結點,根據生物學來定義
-
以上稱爲兩層的神經網絡(輸入層不算)
-
一層中加權的求和,根據非線性方程轉化輸出
-
作爲多層向前神經網絡,理論上,如果有足夠多的隱藏層和足夠大的訓練集,理論上可模擬出任何方程。
3.4.2 設計神經網絡結構
- 使用神經網絡設計數據之前,必須確定神經網絡的層數,以及每層單元的個數
- 特徵向量在傳入輸入層時,通常先被標準化(normalize)0到1之間,爲了加速學習的過程
- 離散型變量可以被編碼成每一個輸入單元對應一個特徵值可能賦的值,比如:特徵值A可能取三個值(a0,a1,a2),可以使用三個輸入單元來代表A;如果A=a0,那麼代表a0的單元值就取1,其他取0;如果A=a1,那麼代表a1的單元值就取1,其他取0,以此類推
- 神經網絡可以用來做分類問題(Classification)問題,也可以解決迴歸問題(regression)問題
- 對於分類問題,如果是兩類,可以用一個輸入單元表示,0和1分別代表兩類
- 如果多於兩類,每一個類別用一個輸入單元表示,輸入層的單元數量通常等於類別數量
- 沒有明確的規則來設計最好有多少個隱藏層,根據實驗測試及誤差以及準確度來改進
- 交叉驗證方法(Cross Validation)
3.4.3 Backpropagation算法
- 通過迭代性來處理訓練集中的實例
- 對比經過神經網絡後,輸入值預測值(predicted value)與真實值(target Value)之間
- 反方向(輸出層-隱藏層-輸入層)來以最小化誤差來更新每個連接的權重
- 算法詳細介紹
輸入:D:數據集,學習率(Learning rate),一個層向前神經網路
輸出:一個訓練好的神經網路(a trained neural network)
初始化權重(weights)和偏向(bias) :隨機初始化到-1到1之間,或者-0.5到0.5之間,每個單元由一個偏向