常见分类算法1--LR 和 SVM算法

1、LR回归原理

        部分讲解参见:https://www.cnblogs.com/bonelee/p/7253508.html

        首先需要清楚的是,LR(Logistic Regression)虽然名字带个回归,但却是经典的分类方法。 为什么分类不用SVM呢?我们对比一下SVM,在二分类问题中,如果你问SVM,它只会回答你该样本是正类还是负类;而你如果问LR,它则会回答你该样本是正类的概率是多少。

        利用Logistic函数(或称为Sigmoid函数),自变量取值范围为(-INF, INF),自变量的取值范围为(0,1),函数形式为:

       

由于sigmoid函数的定义域是(-INF, +INF),而值域为(0, 1)。因此最基本的LR分类器适合于对两分类(类0,类1)目标进行分类。Sigmoid 函数是个很漂亮的“S”形,如下图所示:

logistic  |  sigmoid函数

        由于sigma函数的特性,我们可作出如下的假设:

wKiom1TEnF2hTs5PAABLtf3DlpQ603.jpg

        上式即为在已知样本X和参数θ的情况下,样本X属性正类(y=1)和负类(y=0)的条件概率。将两个公式合并成一个,如下:

wKioL1TEnTnA8ZKSAAA8rx3sZUM132.jpg

        既然概率出来了,那么最大似然估计也该出场了。假定样本与样本之间相互独立,那么整个样本集生成的概率即为所有样本生成概率的乘积:

wKioL1TEnTmCIvnhAACSHATjZaY077.jpg

        为了简化问题,我们对整个表达式求对数,(将指数问题对数化是处理数学问题常见的方法):

wKiom1TEnF7glwX2AABxj9lYg18460.jpg

        满足似然函数(θ)的最大的θ值即是我们需要求解的模型。

        梯度上升算法:就像爬坡一样,一点一点逼近极值。爬坡这个动作用数学公式表达即为:

wKioL1TEnTyxHegQAAAgSFtr9U4431.jpg

        其中,α为步长。

        回到Logistic Regression问题,我们同样对函数求偏导。

wKiom1TEnGHhkXbMAAFCAkpV7Zs421.jpg

          综合以上得到:

wKiom1TEnGTAhlbMAAAfcirD1mM147.jpg

        因此,梯度迭代公式为:

wKiom1TEnGSDl1JuAAAqXOo511s178.jpg

2、LR分类的正则项

        对于线性回归模型,使用L1正则化的模型建叫做Lasso回归,使用L2正则化的模型叫做Ridge回归(岭回归)。

        L1正则化是指权值向量w中各个元素的绝对值之和,通常表示为||w||1,二维平面下L1正则化和J0的交点在坐标轴上很多特征值为0,这也就解释了为什么L1正则化可以产生稀疏模型,进而可以用于特征选择。

        L2正则化是指权值向量w中各个元素的平方和然后再求平方根(可以看到Ridge回归的L2正则化项有平方符号),通常表示为||w||2,二维平面下L2正则化的函数图形是个圆,与方形相比,被磨去了棱角。是的J0和L相交的几率小了很多,所以不会出现稀疏矩阵,却能够抑制过拟合

3、二分类问题--LR的tensorflow实现

import pandas as pd
import numpy as np

column_name = ['Sample code number','Clump Thickness','Uniformity of Cell Size','Uniformity of Cell Shape','Marginal Adhesion',
              'Single Epithelial Cell Size','Bare Nuclei','Bland Chromatin','Normal Nucleoli','Mitoses','Class']

data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data'
                  ,names = column_name)
#将?替换为标准缺失值表示
data = data.replace(to_replace='?',value=np.nan)
#丢弃带有缺失值的数据
data = data.dropna(how='any')
from sklearn.cross_validation import train_test_split
X_train,X_test,y_train,y_test = train_test_split(data[column_name[1:10]],data[column_name[10]],test_size=0.25,random_state=33)

from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import SGDClassifier
#标准化数据,保证每个维度的特征数据方差为1,均值为0,使得预测结果不会被某些维度过大的特征值而主导
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)
#初始化LogisticRegression和SgdClassifier
lr = LogisticRegression()
sgdc = SGDClassifier()

#调用LogisticRegression的fit函数来训练模型,并使用predict函数进行预测
lr.fit(X_train,y_train)
lr_y_predict = lr.predict(X_test)
#调用SGDClassifier中的fit函数来训练模型,并用predict函数来进行预测
sgdc.fit(X_train,y_train)
sgdc_y_predict = sgdc.predict(X_test)

from sklearn.metrics import classification_report
#利用score方法计算准确性
print('Accruacy of LR Classifier:',lr.score(X_test,y_test))
#利用classification_report模块获得召回率,精确率和F1值三个指标
print(classification_report(y_test,lr_y_predict,target_names=['Benign','Malignant']))

print('Accruacy of SGD Classifier',sgdc.score(X_test,y_test))
print(classification_report(y_test,sgdc_y_predict,target_names=['Benign','Maligant']))

4、SVM原理详解

        这里讲解三类向量机:线性可分支持向量机(硬间隔支持向量机)、线性支持向量机(软间隔支持向量机)、非线性支持向量机(通过核函数将非线性特征线性化)

        4.1、线性可分支持向量机和硬间隔

        给定线性可分训练数据集,通过间隔最大化或等价地求解相应的凸二次规划问题学习得到的分离超平面为:

        以及相应的分类决策函数:

        称为线性可分支持向量机

        函数间隔:在超平面 w*x + b = 0确定的情况下, |w*x + b| 能够相对地表示点 z 距离超平面的远近。而 w*x + b 的符号与类标记 y 的符号是否一致能够表示分类是否正确。所以可用量y(w*x + b) 来表示分类的正确性及确信度,也就是函数间隔

        几何间隔:为了防止参数 w 和 b成倍扩大时,超平面不变间隔却变为原来的2倍,这里我们需要的规范化w 和 b两个参数,进行规范化的函数间隔我们称之为几何间隔,这里我们定义 正例y = 1,负例y = -1,几何间隔定义如下:

        ||w||是二范数,这里几何间隔 = 函数间隔 / ||w||,如果||w|| = 1,则两者相等

        间隔最大化:通过参数调整,使得间隔最大化,即求约束最优化问题:

        考虑到几何间隔和函数间隔的关系,改为求如下关系:

        由于这里不是求间隔大小,而是参数 w 和 b使得间隔最大,且最大间隔超平面存在且唯一(证明就算了有兴趣去查查),所以可以转变为最小化(凸二次规划问题),根据下式进行求解就是动态规划,把(x, y)点带入,肯定存在多个w参数,一个一个消去即可:

        支持向量:这里在就是X1 和 X3,这两个点所在的分割平面称为间隔边界

        求解线性可分支持向量机可使用对偶算法,具体可查看----统计学习方法第二版----page140,如果有时间开一个数学专栏再写吧,使用对偶算法主要是对偶问题容易解决且引入了核函数。下面是线性可分支持向量机的对偶解法简述:

  •         构建拉格朗日函数函数,变为极大极小问题

  •         最终经过求极小 求极大 两个步骤,变为求解下式:

  •         根据求出的a,计算参数 w 和 b

        最终得到线性可分支持向量的对偶形式,同时说明分类决策函数只依赖于输入x和输入的内积:

        4.2、线性支持向量机和软间隔

        松弛变量:线性不可分意味着样本点(Xi, Yi)不能满足于函数间隔大于等于1的条件,这样我们只好放宽条件,引入松弛因子ξ ≧ 0,使得函数间隔加上松弛因子大于等于1:

        目标函数变为:

        C值是惩罚参数,一般C值越大对于误分类的惩罚越大,目标函数有两层含义:间隔尽量大、误分类样本尽可能少。线性支持向量机的凸二次规划问题(原始问题)总结如下:

    上式求解得到参数 w* 和 b*,从而计算出分离超平面 w* ・ x + b* = 0和分类决策函数 f(x) = sign(w* ・ x + b*),而这种模型被称为线性支持向量机。原始问题的对偶问题(引入拉格朗日函数,通过求导求极小值,再求极大值)是:

        接下来是,原始问题最优解 和 对偶问题最优解 之间的关系:

        关于线性支持向量机 的 支持向量 说明如下:

        4.3、非线性支持向量机与核函数

        核技巧:通过特征变换,将非线性特征映射到线性特征中去

        核函数:核函数不是 简单的特征 x 到特征 z 的映射关系

        核函数的实例解释如下:

        当映射函数是非线性函数时,SVM模型就变成了非线性支持向量机模型。核技巧可以简单的认为是选择核函数的方法,所选核函数是否有效取决于实验验证,选取核函数同样也需要结合专业知识进行。

        正定核

        正定核的充要条件:

        正定核的等价定义:

        在--统计学习方法第二版--中讲了一大堆,证明充要条件什么的,你看看那就好,工科生不是数学家没必要为难自己,那个坐冷板凳太久了,不需要刻意去理解。但是别的地方能够理解的还是尽力理解对自己有帮助。

        常见核函数:多项式核函数    高斯核函数    字符串核函数()

        多项式核函数:

        高斯核函数:

        非线性支持向量分类机

        SMO(序列最小最优化算法)求解SVM

        

5、SVM分类鸢尾花数据

from sklearn import svm
import numpy as np
from sklearn.model_selection import train_test_split
import pdb
import collections


def iris_type(s):
    it = {b'Iris-setosa': 0, b'Iris-versicolor': 1, b'Iris-virginica': 2}
    return it[s]


def show_accuracy(pre_data, init_data, str_lab):
	init_data = init_data.reshape(len(init_data))
	# print(init_data==pre_data)
	# pdb.set_trace()

	# 
	c = collections.Counter(pre_data == init_data).most_common(2)
	# print(len(c)>1)
	# print(c[0][1]/(c[1][1] + c[0][1]))

	if len(c) > 1:
		if c[0][0] == False:
			accuracy = c[1][1] / (c[1][1] + c[0][1])
		elif c[0][0] == True:
			accuracy = c[0][1] / (c[1][1] + c[0][1])
	elif len(c) == 1:
		if c[0][0] == False:
			accuracy = 0
		else:
			accuracy = 1
	# print(accuracy)			
	print('准确率是:%.3f,此时数据集为:%s' % (accuracy, str_lab))


# 这里数据少可以一次读入,正常情况下添加读入数据
path = './iris.txt' # 数据文件路径
data = np.loadtxt(path, dtype=float, delimiter=',', converters={4: iris_type})
# print(data)

# 切分数据
x, y = np.split(data, (4,), axis=1)
x = x[:, :2]
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1, train_size=0.6)


# 训练模型
clf = svm.SVC(C=0.8, kernel='rbf', gamma=20, decision_function_shape='ovr')
clf.fit(x_train, y_train.ravel())

# 查看模型的分类状况
print(clf.score(x_train, y_train)) # 精度
y_hat = clf.predict(x_train)

# pdb.set_trace()
show_accuracy(y_hat, np.asarray(y_train), '训练集')
print(clf.score(x_test, y_test))
y_hat = clf.predict(x_test)
show_accuracy(y_hat, np.asarray(y_test), '测试集')

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值