幾種常用算法的比較

type

introduce

example

k-nearest neighbors

原理:是一種常用的監督學習方法,給定測試樣本,基於某種距離度量找出訓練集中與其最靠近的k個訓練樣本,然後基於這k個“鄰居”的信息來進行預測。

判定方法:

(1)在分類任務中的可使用“投票法”,即選擇這k個樣本中出現最多的類別標記作爲預測結果;

(2)在迴歸任務中可使用“平均法”,即將這k個樣本的標記平均值作爲預測結果。

(3)還可以根據距離遠近,對樣本進行加權,實現加權平均或加權投票。

(二)注意點:

1、距離度量方法不同,找到的“近鄰”也可能有顯著區別,進而導致分類結果不同。通常是用歐式距離,即平方和開根號。

2、k在其中是一個相當重要的參數,k取值不同時,分類結果會有顯著不同。

優點:適合對稀有事件進行分類(例如當流失率很低時,比如低於0.5%,構造流失預測模型)

特別適合於多分類問題(multi-modal,對象具有多個類別標籤),例如根據基因特徵來判斷其功能分類,kNN比SVM的表現要好

理論成熟,思想簡單,既可以用來做分類也可以用來做迴歸;

可用於非線性分類;

訓練時間複雜度爲O(n);

對數據沒有假設,準確度高,對outlier不敏感;

缺點:

計算量大;

樣本不平衡問題(即有些類別的樣本數量很多,而其它樣本的數量很少);

需要大量的內存。

#1.導入:

分類問題:

from sklearn.neighbors import KNeighborsClassifier

迴歸問題:

from sklearn.neighbors import KNeighborsRegressor

 

#2.創建模型

knnclf = KNeighborsClassifier(n_neighbors=5)

knnrgr = KNeighborsRegressor(n_neighbors=3)

 

#3.訓練

knnclf.fit(X_train,y_train)

 

#4.預測

y_pre = knnclf.predict(x_test)

LinearRegression

數理統計中迴歸分析,用來確定兩種或兩種以上變量間相互依賴的定量關係的一種統計分析方法,其表達形式爲y = w'x+e,其中只有一個自變量的情況稱爲簡單迴歸,多個自變量的情況叫多元迴歸

迴歸說明它的響應是定量(quantitative)的,而不是定性(qualitative)的。

適用數據類型:數值型和標稱型

優點:結果易於理解,計算不復雜

缺點:對非線性的數據擬合不好

          當特徵冗餘,即如果存在多重共線性時,線性迴歸就不太穩定

損失函數: 對於線性迴歸模型,將模型與數據點之間的距離差之和做爲衡量匹配好壞的標準,誤差越小,匹配程度越大

#1.導入from sklearn.linear_model import LinearRegression

#2.創建模型

line = LinearRegression()

#3.訓練

line.fit(X_train,y_train)

#4.預測

y_pre= line.predict(x_test)

Ridge

原理:嶺迴歸是一種專用於共線性數據分析的有偏估計迴歸方法,實質上是一種改良的最小二乘估計法,通過放棄最小二乘法的無偏性,以損失部分信息、降低精度爲代價,獲得迴歸係數更爲符合實際、更可靠的迴歸方法,對病態數據的耐受性遠遠強於最小二乘法。

缺點:通常嶺迴歸方程的R平方值會稍低於普通迴歸分析,但迴歸係數的顯著性往往明顯高於普通迴歸,在存在共線性問題和病態數據偏多的研究中有較大的實用價值。

適用情況:主要適用於過擬合嚴重或各變量之間存在多重共線性的時候

1.嶺迴歸可以解決特徵數量比樣本量多的問題

2.嶺迴歸作爲一種縮減算法可以判斷哪些特徵重要或者不重要,有點類似於降維的效果

3.縮減算法可以看作是對一個模型增加偏差的同時減少方差

#1.導入from sklearn.linear_model import Ridge

#2.創建模型# alpha就是縮減係數lambda# 如果把alpha設置爲0,就是普通線性迴歸

ridge = Ridge(alpha=.5)

#3.訓練#4.預測

X = [[0,0],[0,0],[1,1]]

y = [0,.1,1]

clf.fit(X,y)

print(clf.coef_)

print(clf.intercept_)

Lasso

最小絕對值收斂和選擇算子、套索算法。該方法是一種壓縮估計。它通過構造一個罰函數得到一個較爲精煉的模型,使得它壓縮一些係數,同時設定一些係數爲零。因此保留了子集收縮的優點,是一種處理具有復共線性數據的有偏估計

Lasso 的基本思想是在迴歸係數的絕對值之和小於一個常數的約束條件下,使殘差平方和最小化,從而能夠產生某些嚴格等於0 的迴歸係數,得到可以解釋的模型。將Lasso應用於迴歸,可以在參數估計的同時實現變量的選擇,較好的解決迴歸分析中的多重共線性問題,並且能夠很好的解釋結果.

#1.導入from sklearn.linear_model import Lasso

#2.創建模型

las = Lasso(alpha=0.0001)

#3.訓練

#4.預測

DecisionTreeRegressor

決策樹是是一個監督式學習方法,主要用於分類和迴歸,是一個樹結構(可以是二叉樹或非二叉樹)。其每個非葉節點表示一個特徵屬性上的測試,每個分支代表這個特徵屬性在某個值域上的輸出,而每個葉節點存放一個類別。使用決策樹進行決策的過程就是從根節點開始,測試待分類項中相應的特徵屬性,並按照其值選擇輸出分支,直到到達葉子節點,將葉子節點存放的類別作爲決策結果。

決策樹是一種典型的分類方法,首先對數據進行處理,利用歸納算法生成可讀的規則和決策樹,然後使用決策對新數據進行分析。本質上決策樹是通過一系列規則對數據進行分類的過程。

可以毫無壓力地處理特徵間的交互關係並且是非參數化的,因此不必擔心異常值或者數據是否線性可分

決策樹優勢:

1、計算簡單,易於理解,可解釋性強;

2、比較適合處理有缺失屬性的樣本;

3、能夠處理不相關的特徵;

4、在相對短的時間內能夠對大型數據源做出可行且效果良好的結果。

決策樹劣勢:

1、可能會建立過於複雜的規則,即過擬合。

2、決策樹有時候是不穩定的,因爲數據微小的變動,可能生成完全不同的決策樹。

3、實際決策樹學習算法是基於試探性算法,例如在每個節點實現局部最優值的貪心算法。 這樣的算法是無法保證返回一個全局最優的決策樹。可以通過隨機選擇特徵和樣本訓練多個決策樹來緩解這個問題。

4、有些問題學習起來非常難,因爲決策樹很難表達。如:異或問題、奇偶校驗或多路複用器問題

5、如果有些因素佔據支配地位,決策樹是有偏的。因此建議在擬合決策樹之前先平衡數據的影響因子。

6、不支持在線學習,於是在新樣本到來後,決策樹需要全部重建

#Import Library

#Import other necessary libraries like pandas, numpy...

from sklearn import tree

#Assumed you have, X (predictor) and Y (target) for training data set and x_test(predictor) of test_dataset

# Create tree object

model = tree.DecisionTreeClassifier(criterion='gini') # for classification, here you can change the algorithm as gini or entropy (information gain) by default it is gini

# model = tree.DecisionTreeRegressor() for regression

# Train the model using the training sets and check score

model.fit(X, y)

model.score(X, y)

#Predict Output

predicted= model.predict(x_test)

SVR

支持向量迴歸(support vector regression)是支持向量機(SVM)的重要的應用分支.

SVR迴歸,就是找到一個迴歸平面,讓一個集合的所有數據到該平面的距離最近

1.導入模塊

import numpy as np

import pandas as pd

from pandas import Series,DataFrame

import matplotlib.pyplot as plt

%matplotlib inline

import sklearn.datasets as datasets

#支持向量迴歸

from sklearn.svm import SVR

 

2.生成訓練數據

x = np.linspace(-np.pi,np.pi,60)

y = np.sin(x)

#數據加噪

y[::3]+=0.5-np.random.random(20)

X_train = x.reshape(-1,1)

Y_train = y

 

3.創建支持向量迴歸模型

svr_linear = SVR(kernel='linear')

svr_rbf = SVR(kernel='rbf')

svr_poly = SVR(kernel='poly')

 

4.訓練數據

svr_linear.fit(X_train,Y_train)

svr_rbf.fit(X_train,Y_train)

svr_poly.fit(X_train,Y_train)

 

5.與測試數據

#獲取預測數據自變量範圍

xmin,xmax = X_train.min(),X_train.max()

x_test = np.arange(xmin,xmax,0.01).reshape(-1,1)

#獲取預測數據

linear_y_pre = svr_linear.predict(x_test)

rbf_y_pre = svr_rbf.predict(x_test)

poly_y_pre = svr_poly.predict(x_test)

 

6.繪圖

results = [linear_y_pre,rbf_y_pre,poly_y_pre]

titles = ['Linear','rbf','poly']

plt.figure(figsize=(12,12))

for i,result in enumerate(results):

plt.subplot(3,1,i+1)

plt.scatter(X_train,Y_train)

plt.plot(x_test,result,color='orange')

plt.title(titles[i])

Logistic迴歸(邏輯迴歸)

實際中最常用的就是二分類的Logistic迴歸,用於分類

Logistic迴歸本質上是線性迴歸,只是在特徵到結果的映射中加入了一層函數映射,即先把特徵線性求和,然後使用函數g(z)將最爲假設函數來預測。g(z)可以將連續值映射到0和1上。

Logistic迴歸的主要用途:

•尋找危險因素:尋找某一疾病的危險因素等; 

•預測:根據模型,預測在不同的自變量情況下,發生某病或某種情況的概率有多大; 

•判別:實際上跟預測有些類似,也是根據模型,判斷某人屬於某病或屬於某種情況的概率有多大,也就是看一下這個人有多大的可能性是屬於某病。

Logistic迴歸主要在流行病學中應用較多,比較常用的情形是探索某疾病的危險因素,根據危險因素預測某疾病發生的概率,等等

其損失函數的目的是增加對分類影響較大的數據點的權重,減少與分類關係較小的數據點的權重

優點:

1、預測結果是界於0和1之間的概率;

2、可以適用於連續性和類別性自變量;

3、容易使用和解釋;

缺點:

1、當特徵空間很大時,邏輯迴歸的性能不是很好;

2、容易欠擬合,一般準確度不太高;

3、不能很好地處理大量多類特徵或變量;只能處理兩分類問題(在此基礎上衍生出來的Softmax可以用於多分類),且必須線性可分;

4、預測結果呈“S”型,因此從log(odds)log(odds)向概率轉化的過程是非線性的,在兩端隨着log(odds)log(odds)值的變化,概率變化很小,邊際值太小,slopeslope太小,而中間概率的變化很大,很敏感。 導致很多區間的變量變化對目標概率的影響沒有區分度,無法確定閥值;

5、對於非線性特徵,需要進行轉換;

# -*- coding:utf-8 -*-

import numpy as np

import matplotlib.pyplot as plt

import random

def text2num(string):

    str_list = string.replace("\n", " ").split(" ")

    while '' in str_list:

        str_list.remove('')

    num_list = [float(i) for i in str_list]

    return num_list

def sigmoid(x):

    return 1.0 / (1 + np.exp(-x))

def data_plot(data_list, weight):

    x_data = [list(i[0:2]) for i in data_list if i[2] == 0.0]

    y_data = [list(i[0:2]) for i in data_list if i[2] == 1.0]

    x_data = np.reshape(x_data, np.shape(x_data))

    y_data = np.reshape(y_data, np.shape(y_data))

    linear_x = np.arange(-4, 4, 1)

    linear_y = (-weight[0] - weight[1] * linear_x) / weight[2]

    print(linear_y)

    plt.figure(1)

    plt.scatter(x_data[:, 0], x_data[:, 1], c='r')

    plt.scatter(y_data[:, 0], y_data[:, 1], c='g')

    print(linear_x)

    print(linear_y.tolist()[0])

    plt.plot(linear_x, linear_y.tolist()[0])

    plt.show()

def grad_desc(data_mat, label_mat, rate, times):

    data_mat = np.mat(data_mat)

    label_mat = np.mat(label_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        h = sigmoid(data_mat * weight)

        error = h - label_mat

        weight = weight - rate * data_mat.transpose() * error

    return weight

def random_grad_desc(data_mat, label_mat, rate, times):

    data_mat = np.mat(data_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        for j in range(m):

            h = sigmoid(data_mat[j] * weight)

            error = h - label_mat[j]

            weight = weight - rate * data_mat[j].transpose() * error

    return weight

def improve_random_grad_desc(data_mat, label_mat, times):

    data_mat = np.mat(data_mat)

    m,n = np.shape(data_mat)

    weight = np.ones((n, 1))

    for i in range(times):

        index_data = [i for i in range(m)]

        for j in range(m):

            rate = 0.0001 + 4 / (i + j + 1)

            index = random.sample(index_data, 1)

            h = sigmoid(data_mat[index] * weight)

            error = h - label_mat[index]

            weight = weight - rate * data_mat[index].transpose() * error

            index_data.remove(index[0])

    return weight

def main():

    file = open("/Users/chenzu/Documents/code-machine-learning/data/LR", "rb")

    file_lines = file.read().decode("UTF-8")

    data_list = text2num(file_lines)

    data_len = int(len(data_list) / 3)

    data_list = np.reshape(data_list, (data_len, 3))

    data_mat_temp = data_list[:, 0:2]

    data_mat = []

    for i in data_mat_temp:

        data_mat.append([1, i[0], i[1]])

    print(data_mat)

    label_mat = data_list[:, 2:3]

    #梯度下降求參數

    weight = improve_random_grad_desc(data_mat, label_mat, 500)

    print(weight)

    data_plot(data_list, weight)

if __name__ == '__main__':

    main()

 

樸素貝葉斯

優點:

樸素貝葉斯模型發源於古典數學理論,有着堅實的數學基礎,以及穩定的分類效率;

對小規模的數據表現很好,能個處理多分類任務,適合增量式訓練;

對缺失數據不太敏感,算法也比較簡單,常用於文本分類。

缺點:

需要計算先驗概率;

分類決策存在錯誤率;

對輸入數據的表達形式很敏感。

import numpy as np
 
class NativeBayes:
    def __init__(self):
        # log(P(Y)), Y = 0,1
        self.log_label_0_ratio = 0
        self.log_label_1_ratio = 0 
        # array of feature weights
        self.weights = None     
        # log value of feat vector
        self.log_label_0_vec = None
        self.log_label_1_vec = None
        
    def fit(self, data_set, labels, weights):
        self.weights = weights
        data_mat = np.array(data_set)
        data_num = len(data_mat)
        feat_num = len(data_mat[0])
        label_1_ratio = sum(labels) / float(data_num)
        label_0_ratio = 1 - label_1_ratio     
        self.log_label_1_ratio = np.log(label_1_ratio)
        self.log_label_0_ratio = np.log(label_0_ratio)    
        # using Laplace smoothing, initialization with alpha = 1
        label_1_feat_array = np.ones(feat_num)
        label_0_feat_array = np.ones(feat_num)
        label_1_feat_sum = float(feat_num)
        label_0_feat_sum = float(feat_num)       
        for i in range(data_num):
            if labels[i] == 0:
                label_0_feat_array += data_mat[i]
                label_0_feat_sum += sum(data_mat[i])
            else:
                label_1_feat_array += data_mat[i]
                label_1_feat_sum += sum(data_mat[i])
        self.log_label_0_vec = np.log(label_0_feat_array / label_0_feat_sum)
        self.log_label_1_vec = np.log(label_1_feat_array / label_1_feat_sum)  
        return self
    
    def predict(self, data):
        p0 = sum(self.log_label_0_vec * data * self.weights) + self.log_label_0_ratio
        p1 = sum(self.log_label_1_vec * data * self.weights) + self.log_label_1_ratio
        if p0 > p1:
            return 0
        else:
            return 1

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章