1. 程式人生 > 其它 >機器學習0——基礎知識和線性迴歸

機器學習0——基礎知識和線性迴歸

師兄的部落格,畢業了他沒維護了,我轉過來。原文地址 https://blog.csdn.net/LogHouse/article/details/90550608

@

目錄

基礎知識至線性迴歸

  從頭學習周志華版的機器學習,同時準備使用Python實現一些相關的方法,以及一些小的專案。因為Python是新手,也準備借這次機會熟悉並掌握,程式碼方面有一些笨拙,希望慢慢改進、進步。

一些問題與概念

1、機器學習的概念是什麼?機器學習學的是什麼?
機器學習通過計算的手段利用經驗(通常為資料)來改善系統自身效能。
研究的主要內容是關於計算機上從資料中產生“模型”的演算法,即“學習演算法”。P1
2、什麼叫做泛化能力,我們可以通過哪些途徑增強我們訓練出的模型的泛化能力?
學得模型適用於新樣本的能力成為“泛化能力”。
假設樣本服從一個未知的分佈\(\mathcal{D}\),得到關於\(\mathcal{D}\)的資訊越多,泛化能力越強。通常可以增加訓練樣本數目,保證每個樣本是獨立地從這個分佈上取樣獲得。
3、假設空間與版本空間的區別與聯絡是什麼?
假設空間:該問題所有假設組成的空間,即所有假設的集合。
版本空間:在假設空間中與訓練集一致的假設的集合。
版本空間是屬於假設空間的。
4、歸納偏好的概念以及它的作用是什麼?
機器學習過程中對某型別假設的偏好稱為“歸納偏好”。
因為訓練集對應的版本空間包含的假設可能不唯一,對於某個具體的學習演算法必須產生一個模型,這時學習演算法的歸納偏好會確定採用哪個假設(有種做決策的感覺),可以看作學習演算法對假設進行選擇的啟發式或“價值觀”。
5、什麼是過擬合、欠擬合?如何避免這些情況?
過擬合:將訓練樣本的某些自身特點(訓練樣本多有的)當作了所有潛在樣本都會具有的一般性質。
欠擬合:與過擬合相對,指對訓練樣本的一般性質尚未學習好。
處理欠擬合:在決策樹學習中擴充套件分支,在神經網路學習中增加訓練輪次。
處理過擬合:控制模型複雜度,增加訓練樣本數目。
6、什麼是交叉驗證?什麼時候要使用交叉驗證?為什麼?
交叉驗證將資料集D劃分為k個大小相似的互斥子集,使每個子集儘可能保持資料分佈的一致性(即從D中採用分層取樣得到)。然後每次將k-1子集作為訓練集,剩下的1個作為測試集,進行k次訓練和測試,返回k個測試結果的均值。
作用:對學習器的泛化誤差進行評估。
可以增加評估結果的穩定性和保真性(跟k有關)。
7、如何評價模型效能?常用的效能指標有哪些,寫出公式?
使用“效能度量”的方式。下面公式中D為樣例集,m為樣例個數,xi和yi分別為第i個樣本及其對應的真實標記。
1)均方誤差:\(E(f;D)=\frac{1}{m}\sum^{m}_{i=1}(f({\bm x}_i)-y_i)^2\)
對於資料分佈\(\mathcal{D}\)和概率分佈函式\(p(⸱)\)\(E(f;\mathcal{D})=\frac{1}{m}\int_{{\bm x}-\mathcal{D}}(f({\bm x})-y)^2p({\bm x})d{\bm x}\)
2)錯誤率:\(E(f;D)=\frac{1}{m}\sum^{m}_{i=1}\Gamma(f({\bm x}_i)\neq y_i)^2\)
精度:\(\textrm{acc}(f;D)=\frac{1}{m}\sum^{m}_{i=1}\Gamma(f({\bm x}_i)= y_i)^2=1-E(f;D)\)
8、偏差與方差是什麼?過擬合,欠擬合,分別對應偏差與方差的什麼情況?
\(y_D\)\({\bm x}\)在資料集中的標記,\(\bar f()\)為學習演算法的期望預測。
方差:\(var({\bm x})= \mathbb{E}_D[(f(\bm{x};D)-\bar f (\bm{x}))^2]\)
噪聲:\(\varepsilon^2= \mathbb{E}_D[(y_D-y)^2]\)
偏差:期望輸出與真實標記的差別:\(var({\bm x})= \mathbb{E}_D[(\bar f(\bm{x})-y)^2]\)
欠擬合時偏差大(主導),過擬合時方差大(主導)。
9、特徵歸一化是什麼?為什麼要歸一化?常用的歸一化方法有哪些?
不同評價指標往往具有不同的量綱和量綱單位,這樣的情況會影響到資料分析的結果,為了消除指標之間的量綱影響,需要進行資料標準化處理(特徵歸一化),以解決資料指標之間的可比性。原始資料經過資料標準化處理後,各指標處於同一數量級,適合進行綜合對比評價。
線性函式歸一化(Min-Max Scaling):將原始資料進行線性的變換,並確保新的資料均對映到[0,1]區間內,實現對原始資料的等比縮放:
$$X_{nrom}=\frac{X-X_{min}}{X_{max}-X_{min}}$$
0均值歸一化(Standardization):將原始資料均對映到均值為0,標準差為1的分佈上。具體來說,假設原始特徵的均值為μ、標準差為σ,那麼歸一化公式定義為:\[z=\frac{x-\mu}{\sigma} \]
10、什麼是梯度下降演算法?寫出具體公式,解釋小批量隨機梯度下降,隨機梯度下降
梯度下降法(用到梯度的確定型最優化演算法):梯度可以反映函式下降的陡峭程度,梯度下降演算法沿著函式最陡峭(梯度最小)的方向往前走一定步長,反覆此過程直至找到最優解。
隨機梯度下降(Stochastics Gradient Descent, SGD):每次迭代只計算一個樣本的損失函式(loss),再逐步遍歷所有樣本。特點:區域性震盪,總體收斂。
小批量隨機梯度下降(mini-batch SGD):為了兼顧穩定下降和隨機特性以及小計算量。每次迭代選取總體樣本中的一小批樣本計算損失函式,逐步遍歷所有樣本。

線性迴歸的Python實現及測試

線性迴歸

線性迴歸模型

一般的線性方程
\(f(x)=w_1x_1+w_2x_2+...+w_nx_n+b\)   寫成向量形式\(\Rightarrow f(\bm{x})= \bm{w} ^T\bm{x}+b\)

線性迴歸
線性迴歸使用一般的線性方程做迴歸,即為處理的資料\(\textbf{X}\)建立一個合適的線性模型,也就是說需要確定一組合適的\(\bm{w}\)\(b\)。值得注意的是將\(\textbf{X}\)中的每組資料\(\bm{x}_i\)替換為\(\hat{\bm{x}}_i=(\bm{x}_i;1)\),則可以將\(\bm{w}\)\(b\)\(\hat{\bm{w}}=(\bm{w};b)\)代替。模型可以替換為\(f(\hat{\bm{x}}_i)= \hat{\bm{w} }^T\bm{x}_i\)。在Python中:

'''線性迴歸模型'''
def modelLR(x, w):
    fx = dot(x, w)
    return fx

模型合不合適可以根據\(f(x)\)和真實的\(y\)之間的差距來判斷,通常我們使用損失函式衡量它們之間差距。

損失函式

均方誤差是線上性迴歸問題中常用的損失函式,寫成:

\[L=\frac{1}{m}\sum^{m}_{i=1}(f(\bm{x}_i)-y)^2 \]

通常我們認為損失函式越小,模型越合適,也就是說模型的求解轉化為了一個最優化問題,在這個問題中目標函式是損失函式,決策變數為\(\hat{\bm{w} }\)。(基於均方誤差最小化來進行模型求解的方法稱為最小二乘法)

'''損失函式'''
def lossFun(w, x, y):
    funError = 0
    x = mat(x)
    for i in range(0, size(y, 0)):
        x1 = x[i, :]
        y1 = y[i, 0]
        fx = modelLR(x1, w)
        funError += (fx - y1)**2
    return funError/size(y, 0)

最速下降法

有了優化問題就需要優化方法,迴歸問題中通常使用梯度下降法,它需要確定兩樣東西:方向步長
我使用的是最速下降法,方向\(d_k\)為梯度的負方向:
下面是梯度方向的計算

'''計算梯度'''
def calcGrad(h, x, y, w):   # 計算梯度
    dkCol = size(w, 0)
    dk = ones((1, dkCol))
    for i in range(0, size(w, 0)):
        w1 = w.copy()
        w2 = w.copy()
        w1[i] = w1[i] - h
        w2[i] = w2[i] + h
        y1 = lossFun(w1, x, y)
        y2 = lossFun(w2, x, y)
        dk[0, i] = (y2-y1)/(2*h)
    return dk

步長:精確法為:

\[\alpha_k=\arg \min\limits_{\alpha\geq0}f(\hat{\bm{w}} _k+\alpha d_k) \]

其中:\(\alpha_k\)需要滿足:

\[\phi'(\alpha)=\frac{\rm{d}}{{\rm d}\hat{\bm{w}} _k}f(\hat{\bm{w}} _k+\alpha d_k)|_{\alpha=\alpha_k}=\nabla f(\hat{\bm{w}} _k+\alpha_k d_k)^Td_k=0 \]
'''計算步長'''
def calcStep(dk, x, y, w):  # 計算步長
    ak = 1
    for i in range(0, 20):
        newF = lossFun(w+ak*dk, x, y)
        oldF = lossFun(w, x, y)
        if (newF<oldF):
            break
        else:
            ak = ak/2
    return ak

整體的最速下降法為:

'''最速下降法訓練'''
def steepest(x, y, w):
    epsilon = 1e-5
    h = 1e-5
    maxIter = 1e3
    for i in range(0, int(maxIter)):
        grad = calcGrad2(h, x, y, w)
        dk = -grad.T
        ak = calcStep(dk, x, y, w)
        neww = w + ak*dk
        if abs(lossFun(neww, x, y)-lossFun(w, x, y)) <= epsilon:
            break
        w = neww
    return w, lossFun(w, x, y)

資料預處理(numpy)

一個numpy中的 矩陣運算方法帖子

讀取檔案

# 載入資料
path = "D:/事項/機器學習學習/week1/"
train = pd.read_csv(path + 'train.csv', engine='python', encoding='gbk')
test = pd.read_csv(path + 'test.csv', engine='python', encoding='gbk')
yt = pd.read_csv(path + 'answer.csv', engine='python', encoding='gbk')
setTrainX = train.values
setTestX = test.values
setTrainX[setTrainX == "NR"] = 0 #替換操作
setTestX[setTestX == "NR"] = 0

此時讀取出的檔案為panda的DataFrame格式,通過DataFrame.values可以得到ndarray格式的資料。

numpy中的矩陣調整

使用hstack(A, B) 橫向結合兩個矩陣,需要保證AB矩陣列數相等vstack(A, B)縱向結合兩個矩陣,需要保證AB矩陣行數相等
因為在這次資料處理中需要迴圈著結合矩陣,啟動時需要有一個矩陣,使用empty(a, b)產生的矩陣並不會被覆蓋,所以用了一個很蠢的辦法:

tempX = ones((18, 1))
for i in range(0, size(setTrainX, 0) - 18, 18):
	tempXX = setTrainX[i:i+18, :]
    tempX = hstack((tempX, tempXX))
tempX = tempX[:, 1:]

ndarray中的資料型別轉化

矩陣形式的ndarray的資料不能使用強制型別轉換的方法改變資料型別,它的資料型別可以通過ndarray.dtype檢視,直接更改dtype會引起資料的解釋錯誤,即記憶體中儲存的內容不變,僅改變了解釋方式。
接著上面的處理,目前的資料的dtype為 “U32” 是字串型別,不能參與運算,需要改為浮點型,此時需要用到 ndarray.astype(type) 函式。

x = x.astype(float)

值得注意的是,引數float實際上是轉換為 “float64” 型別(預設的浮點型別)。

標準化

標準化會影響演算法的收斂速度。

ss= StandardScaler()
for i in range(0, size(x, 1)):
    ss.fit(x[:, i].reshape(-1, 1))
    x[:, i] = ss.transform(x[:, i].reshape(-1, 1)).T

注意ndarray格式的資料需要 .reshape(-1, 1) 才能使用 .fit() 函式,原因暫時不知道

矩陣呼叫

ndarray下的向量似乎不能使用類似A[a, b]的呼叫方法,但是用mat(A)轉化為matrix型別就可以使用了。