pandazjd 2018-06-08
我猜现在你已经了解了线性回归和逻辑回归算法。如果没有,我建议您在继续支持向量机之前先看看它们。支持向量机是每个机器学习专家都应该拥有的另一个简单算法。支持向量机由于具有较高的精度和较低的计算能力而受到许多人的青睐。支持向量机,简称SVM,可用于回归和分类任务。但在分类目标中应用广泛。
支持向量机算法的目标是在一个N维空间(N -特征个数)中找到一个超平面,该超平面可以清晰地对数据点进行分类。
可能的超平面
为了分离两类数据点,可以选择许多可能的超平面。我们的目标是找到一个具有最大余量的平面,即两个类的数据点之间的最大距离。最大化边缘距离可以提供一些强化,以便将来的数据点可以更自信地进行分类。
2D和3D特征空间中的超平面
超平面是帮助分类数据点的决策边界。落在超平面两侧的数据点可归因于不同的类别。此外,超平面的尺寸取决于特征的数量。如果输入特征的数量是2,那么超平面就是一条线。如果输入特征的数量是3,则超平面变成二维平面。当特征的数量超过3时变得难以想象。
支持向量是更接近超平面并影响超平面的位置和方向的点数据点。使用这些支持向量,我们可以最大化分类器的边际。删除支持向量将会改变超平面的位置。这些是帮助我们构建SVM的要点。
在logistic回归中,我们取线性函数的输出,利用sigmoid函数压缩在[0,1]范围内的值。如果squash的值大于阈值(0.5),我们给它赋一个标签1,否则我们给它赋一个标签0。在SVM中,我们取线性函数的输出,如果输出大于1,我们用一个类来标识它,如果输出是-1,我们用另一个类来标识它。由于阈值在SVM中被更改为1和-1,所以我们得到了作为边缘的值([-1,1])的增强范围。
在SVM算法中,我们希望最大限度地增加数据点与超平面之间的距离。最大限度地增加页边的损失函数是hinge loss。
hinge loss函数(左侧的函数可以表示为右侧的函数)
如果预测值和实际值具有相同的符号,则成本为0。如果他们不是,我们然后计算损失值。我们还添加了正则化参数的成本函数。正则化参数的目标是平衡利润率最大化和损失。添加正则化参数后,成本函数如下所示。
SVM的损失函数
现在我们已经有了损失函数,我们对权重采取偏导数来找到梯度。使用梯度,我们可以更新我们的权重。
梯度
当没有错误分类时,即我们的模型正确地预测了我们的数据点的类别时,我们只需要从正则化参数更新梯度
Gradient Update — No misclassification
当存在错误分类时,也就是说,我们的模型在预测我们数据点的类别时出现错误,我们会将损失与正则化参数一起纳入以执行梯度更新
Gradient Update — Misclassification
我们将用来实现我们的SVM算法的数据集是Iris数据集。你可以从这个链接下载它(https://www.kaggle.com/jchen2186/machine-learning-with-iris-dataset/data)。
import pandas as pd
df = pd.read_csv('/Users/rohith/Documents/Datasets/Iris_dataset/iris.csv')
df = df.drop(['Id'],axis=1)
target = df['Species']
s = set()
for val in target:
s.add(val)
s = list(s)
rows = list(range(100,150))
df = df.drop(df.index[rows])
由于Iris数据集有三个类,我们将删除其中一个类。这给我们留下了二元类分类问题。
import matplotlib.pyplot as plt
x = df['SepalLengthCm']
y = df['PetalLengthCm']
setosa_x = x[:50]
setosa_y = y[:50]
versicolor_x = x[50:]
versicolor_y = y[50:]
plt.figure(figsize=(8,6))
plt.scatter(setosa_x,setosa_y,marker='+',color='green')
plt.scatter(versicolor_x,versicolor_y,marker='_',color='red')
plt.show()
可视化数据点
此外,我们还可以使用四个特性。我们将只使用两个特性,萼片长度和花瓣长度。我们把这两个特征画出来,让它们形象化。从上面的图中,您可以推断出可以使用一条直线来分离数据点。
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
import numpy as np
## Drop rest of the features and extract the target values
df = df.drop(['SepalWidthCm','PetalWidthCm'],axis=1)
Y = []
target = df['Species']
for val in target:
if(val == 'Iris-setosa'):
Y.append(-1)
else:
Y.append(1)
df = df.drop(['Species'],axis=1)
X = df.values.tolist()
## Shuffle and split the data into training and test set
X, Y = shuffle(X,Y)
x_train = []
y_train = []
x_test = []
y_test = []
x_train, x_test, y_train, y_test = train_test_split(X, Y, train_size=0.9)
x_train = np.array(x_train)
y_train = np.array(y_train)
x_test = np.array(x_test)
y_test = np.array(y_test)
y_train = y_train.reshape(90,1)
y_test = y_test.reshape(10,1)
我们提取所需的特性并将其分解为训练和测试数据。90%的数据用于培训,其余的10%用于测试。现在让我们使用numpy库构建SVM模型。
## Support Vector Machine
import numpy as np
train_f1 = x_train[:,0]
train_f2 = x_train[:,1]
train_f1 = train_f1.reshape(90,1)
train_f2 = train_f2.reshape(90,1)
w1 = np.zeros((90,1))
w2 = np.zeros((90,1))
epochs = 0
alpha = 0.0001
while(epochs < 10000):
y = w1 * train_f1 + w2 * train_f2
prod = y * y_train
print(epochs)
count = 0
for val in prod:
if(val >= 1):
cost = 0
w1 = w1 - alpha * (2 * 1/epochs * w1)
w2 = w2 - alpha * (2 * 1/epochs * w2)
else:
cost = 1 - val
w1 = w1 + alpha * (train_f1[count] * y_train[count] - 2 * 1/epochs * w1)
w2 = w2 + alpha * (train_f2[count] * y_train[count] - 2 * 1/epochs * w2)
count += 1
epochs += 1
α(0.0001)是学习率和正则化参数设置为1/epochs。因此,正则化值减少了epochs增加的次数。
from sklearn.metrics import accuracy_score
## Clip the weights
index = list(range(10,90))
w1 = np.delete(w1,index)
w2 = np.delete(w2,index)
w1 = w1.reshape(10,1)
w2 = w2.reshape(10,1)
## Extract the test data features
test_f1 = x_test[:,0]
test_f2 = x_test[:,1]
test_f1 = test_f1.reshape(10,1)
test_f2 = test_f2.reshape(10,1)
## Predict
y_pred = w1 * test_f1 + w2 * test_f2
predictions = []
for val in y_pred:
if(val > 1):
predictions.append(1)
else:
predictions.append(-1)
print(accuracy_score(y_test,predictions))
我们现在clip权重,因为测试数据只包含10个数据点。我们从测试数据中提取特征并预测值。我们得到了预测,并将其与实际值进行比较,并打印出模型的准确性。
我们的SVM模型的准确性
还有一种简单的方法来实现SVM算法。我们可以使用Scikit学习库并调用相关函数来实现SVM模型。代码行数大大减少。
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
clf = SVC(kernel='linear')
clf.fit(x_train,y_train)
y_pred = clf.predict(x_test)
print(accuracy_score(y_test,y_pred))