機器學習概述
什麼是機器學習
機器學習是一門能夠讓編程計算機從數據中學習的計算機科學.
一個計算機程序在完成任務T之後, 獲得經驗E, 其表現爲P, 如果任務T的性能表現§, 隨着E的增加而增加, 那麼這樣的計算機程序就被稱爲機器學習系統. 擁有自我完善, 自我增進, 自我適應的特點.
爲什麼需要機器學習
- 自動化的升級和維護
- 解決那些算法過於複雜,甚至根本就沒有算法的問題
- 在機器學習的過程中協助人類對事物進行深刻理解
機器學習的問題
- 建模問題
所謂機器學習, 形式上可以這麼理解: 在數據中通過統計或推理的方法, 尋找一個接受特定輸入x, 並給出預期輸出y的功能函數f(x). - 評估問題
針對已知輸入, 函數給出的輸出(預測值)與實際輸出(目標值)之間存在一定的誤差, 因此需要構建一個評估體系, 根據誤差的大小判定函數的優劣. - 優化問題
學習的核心在於改善自身的性能, 通過數據對算法的反覆錘鍊, 不斷提升函數預測的準確性, 直到獲得能夠滿足實際需求的最優解決方案.
機器學習的種類
監督學習, 無監督學習, 半監督學習, 強化學習
- 監督學習: 用已知的輸出評估模型的性能, 從而引導模型優化.
- 無監督學習: 在沒有已知輸出的情況下, 僅僅根據輸入信息的相關性, 進行類別的劃分.
- 半監督學習: 先通過無監督學習劃分類別, 再根據人工標記, 通過有監督學習預測輸出.
- 強化學習: 通過對不同決策結果的獎勵和懲罰, 使機器學習系統經過長時間訓練後, 越來越傾向於給出接近期望結果的輸出.
批量學習和增量學習 - 批量學習: 將學習的過程和應用的過程分開, 用全部的訓練數據訓練模型, 然後在應用場景中實現預測, 當預測結果不夠理想時, 重新回到學習過程
- 增量學習: 將學習的過程和應用的過程統一起來, 在應用的同時以增量的方式不斷學習新的內容, 邊訓練邊預測, 邊預測邊訓練.
基於實例的學習和基於模型的學習 - 基於實例的學習: 以歷史數據作爲經驗, 尋找與待預測輸入最接近的樣本, 以其輸出作爲預測結果
- 基於模型的學習: 以歷史數據作爲經驗, 建立聯繫輸入與輸出的某種數學模型, 將待預測輸入代入該模型, 預測結果.
機器學習的一般過程
數據清理
- 數據收集(數據檢索, 數據挖掘, 爬蟲)
- 數據清洗
機器學習 - 選擇模型(算法)
- 訓練模型(算法)
- 評估模型(工具, 框架, 算法)
- 測試模型
業務運維 - 應用模型
- 維護模型
機器學習的典型應用
股價預測, 推薦引擎, 自然語言識別(NLP), 語言, 圖像, 人臉識別等.
機器學習的基本問題
- 迴歸問題: 根據已知的輸入和輸出尋找某種最佳的模型, 將未知輸出的輸入代入模型, 得到連續的輸出
- 分類問題: 根據已知的輸入和輸出尋找某種性能最佳的模型, 將未知輸出的輸入代入模型, 得到離散的輸出.
- 聚類問題: 根據已知輸入的相似程度, 將其劃分成不同的羣落.
- 升維,降維問題: 在性能損失儘可能小的情況下, 實現模型業務.
數據預處理
數據樣本矩陣格式
年齡 | 學歷 | 經驗 | 性別 | 月薪 |
27 | 碩士 | 2 | 女 | 12000 |
24 | 本科 | 1 | 男 | 8000 |
... | ... | ... | ... | ... |
##均值移除(標準化)
由於一個樣本的不同特徵值差異較大, 不利於使用現用機器學習算法進行樣本處理. 所以可以使用均值移除讓樣本矩陣中每組特徵值的平均值爲0, 標準差爲1
如何使樣本矩陣中每組特徵平均值爲0?
年齡: 17 20 23
mean(年齡) = 20
a = -3
b = 0
c = 3
如何使樣本矩陣中每組特徵標準差爲1?
a = -3
b = 0
c = 3
s = std(a, b, c)
結果: [a/s, b/s, c/s]
sklearn提供了均值移除的相關API:
import sklearn.preprocessing as sp
A = sp.scale(array)
案例:
import sklearn.preprocessing as sp
import numpy as np
raw_samples = np.array([
[17, 100, 4000],
[20, 80, 5000],
[23, 75, 5500]
])
std_samples = sp.scale(raw_samples.astype('float64'))
print(std_samples)
print(std_samples.mean(axis=0))
print(std_samples.std(axis=0))
範圍縮放
將樣本矩陣中的每一列的最小值與最大值設定爲相同的區間, 統一各列特徵值的範圍. 一般情況下會把特徵值縮放至[0, 1]區間.
如何使一組特徵值的最小值爲0呢?
原特徵: [17, 20, 23]
每個元素減去特徵值的最小值: [0, 3, 6]
如何使一組特徵值的最大值爲1呢?
[0, 3, 6]
把特徵值數組每個元素除以最大值: [0, 0.5, 1]
sklearn提供了範圍縮放相關API:
# 獲取MinMax範圍縮放器, 定義縮放範圍[0, 1]
mms = sp.MinMaxScaler(feature_range(0, 1))
# 返回縮放結果
result = mms.fit_transform(原始樣本矩陣)
案例:
import numpy as np
import sklearn.preprocessing as sp
raw_samples = np.array([
[17, 100, 4000],
[20, 80, 5000],
[23, 75, 5500]
])
print(raw_samples)
mms = sp.MinMaxScaler(feature_range=(0, 1))
result = mms.fit_transform(raw_samples)
print(result)
該範圍縮放過程也可以這麼理解:
當x=17時, y=0; 當x=23時, y=1; 問: 當x=20時, y=??
KaTeX parse error: Expected 'EOF', got '\
' at position 127: …rix}
\right]
= \̲
̲\left[
\begin{m…
mms_samples = raw_samples.copy().astype('float64')
for col in mms_samples.T:
col_min = col.min()
col_max = col.max()
a = np.array([
[col_min, 1],
[col_max, 1]
])
b = np.array([0, 1])
x = np.linalg.solve(a, b)
# 計算 y = kx + b
col *= x[0]
col += x[1]
print(mms_samples)
歸一化
有些情況每個樣本的每個特徵值具體是多少並不重要, 但每個樣本特徵值的佔比更加重要.
Python | Java | Php | |
2017 | 10 | 20 | 5 |
2018 | 8 | 5 | 0 |
... | ... | ... | ... |
sklean提供的歸一化相關API:
# array: 原始樣本矩陣
# norm: 範數
# l1: l1範數, 這組數據每個元素絕對值之和爲1
# l2: l2範數, 這組數據每個元素平方和爲1
sp.normalize(array, norm='l1')
案例:
import numpy as np
import sklearn.preprocessing as sp
raw_samples = np.array([
[17, 100, 4000],
[20, 80, 15000],
[23, 75, 15500]
]).astype('float64')
print(raw_samples)
# 歸一化處理
nor_samps = sp.normalize(raw_samples, norm='l1')
print(nor_samps)
print(abs(nor_samps).sum(axis=1))
# 自己算
nor_samps = raw_samples.copy()
for row in nor_samps:
row /= abs(row).sum()
print(nor_samps)
print(abs(nor_samps).sum(axis=1))
二值化
有些業務並不需要分析矩陣的詳細完整數據(比如圖像邊緣只需要分析圖像邊緣即可), 可以根據一個事先給定的閾值, 用0和1對特徵值進行轉換, 分別表示不高於或高於閾值.二值化後數組中每個元素非0即1, 達到簡化數學模型的目的.
sklearn提供二值化相關的API:
# 給出閾值, 獲取二值化器
bin = sp.Binarizer(threshold='閾值')
# 對原始樣本矩陣執行二值化預處理操作
result = bin.transform(原始樣本矩陣)
案例:
raw_samples = np.array([
[17, 100, 4000],
[20, 80, 15000],
[23, 75, 15500]
]).astype('float64')
print(raw_samples)
bin = sp.Binarizer(threshold=80)
bin_samples = bin.transform(raw_samples)
print(bin_samples)
raw_samples[raw_samples<=80] = 0
raw_samples[raw_samples>80] = 1
print(raw_samples)
獨熱編碼
爲樣本特徵的每個值簡歷一個由一個1和若干個0組成的序列, 用該序列對所有的特徵值進行編碼.
2個數 3個數 4個數
1 3 2
7 5 4
1 8 6
7 3 9
爲每個數組進行編碼
1-10 3-100 2-1000
7-01 5-010 4-0100
8-001 6-0010
9-0001
編碼後得到的最終樣本矩陣:
101001000
010100100
100010010
011000001
獨熱編碼相關的API:
# 創建獨熱編碼器對象
# sparse: 是否採用緊縮格式
# dtype: 數據類型
ohe = sp.OneHotEncoder(sparse=是否採用緊縮格式, dtype=數據類型)
# 對原始樣本矩陣進行處理, 返回獨熱編碼後的樣本矩陣
result = ohe.fit_transform(原始樣本矩陣)
案例:
raw_samples = np.array([
[17, 100, 4000],
[20, 80, 15000],
[23, 75, 15500]
]).astype('float64')
print(raw_samples)
# 獨熱編碼
ohe = sp.OneHotEncoder(sparse=True, dtype=int)
ohe_samples = ohe.fit_transform(raw_samples)
print(ohe_samples)
# 獲取ohe的編碼字典
ohe_dict = ohe.fit(raw_samples)
print(ohe_dict)
ohe_samples = ohe_dict.transform(raw_samples)
print(ohe_samples)
標籤編碼
根據字符串形式的特徵值在特徵序列中的位置, 爲其制定一個數字標籤, 用於提供給基於數值算法的學習模型.
標籤編碼相關的API:
# 獲取標籤編碼器
lbe = sp.LabelEncoder()
# 對原始樣本矩陣執行標籤編碼, 返回編碼完畢後的
result = lbe.fit_transform(原始樣本矩陣)
# 給出編碼矩陣, 反向逆推出原始樣本矩陣
samples = lbe.inverse_transform(result)
案例:
raw_samples = np.array([
'audi', 'ford', 'audi', 'toyota',
'ford', 'bmw', 'toyota', 'byd',
'audi'
])
# 執行標籤編碼
lbe = sp.LabelEncoder()
lbe_samples = lbe.fit_transform(raw_samples)
print(lbe_samples)
inv_samples = lbe.inverse_transform(lbe_samples)
print(inv_samples)
線性迴歸
線性迴歸的本質爲針對符合線性模型的一組數據, 可以找到一個線性方程擬合樣本數據. 從而給出自變量後, 通過線性方程實現預測輸出的目的.
輸入 輸出
0.5 5.0
0.6 5.5
0.8 6.0
1.1 6.8
1.4 7.0
...
y = kx + b
預測函數: y = w0 + w1x
x: 輸入
y: 輸出
w0 w1: 模型參數
所謂模型的訓練, 就是根據已知的x與y, 找到最佳的模型參數w0 w1, 使得儘可能的精確描述所有輸入和輸出的關係(誤差最小).
單樣本誤差:
根據預測函數求出輸入爲x時的預測值: y’ = w0 + w1x.
單樣本誤差則爲: 1/2(y’ - y)2
總樣本誤差:
把所有單樣本誤差相加即是總樣本誤差: 1/2Σ(y’ - y)2
損失函數:
loss = 1/2Σ(w0 + w1x - y)2
所以最終的結果即是需要找到一組w0 w1使得loss函數值最小.