几种常用算法的比较

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

 

点赞