感知机
二分类问题的线性分类模型,输入为实例的特征向量 x ∈ R n x \in R^n x∈Rn,输出为实例的类别{+1,-1}。
数据集线性可分,即存在超平面 S , w ∗ x + b = 0 w*x +b = 0 w∗x+b=0 能够将数据集的正实例和负实例完全正确的划分到超平面的两侧。
感知机学习的目的是求出将训练数据进行线性划分的分离超平面,属于判别模型。
模型
f ( x ) = s i g n ( w ∗ x + b ) f(x) = sign(w*x + b) f(x)=sign(w∗x+b)
w 和 b w 和 b w和b为感知机模型的参数, w ∈ R n w \in R^n w∈Rn为权值向量, b ∈ R b \in R b∈R 叫做偏置, w ∗ x w*x w∗x 表示 w 和 x w 和 x w和x的内积,sign为符号
s i g n ( x ) = { 1 , x ⩾ 0 − 1 , x < 0 sign(x) = \begin{cases} 1, & x \geqslant 0 \\ -1, & x< 0 \end{cases} sign(x)={1,−1,x⩾0x<0
假设空间:特征空间中的所有线性分类模型或线性分类器,即函数集合 { f ∣ f ( x ) = w ∗ x + b } \{f|f(x) = w*x +b\} {f∣f(x)=w∗x+b},属于非概率模型
策略
误分类点到超平面S的总距离: − 1 ∥ w ∥ ∑ x i ∈ M y i ( w ∗ x i + b ) - \frac{1}{\Vert w \Vert}\sum_{x_i \in M}{y_{i}(w*x_{i} + b)} −∥w∥1∑xi∈Myi(w∗xi+b)
损失函数
L
(
w
,
b
)
=
−
∑
x
i
∈
M
y
i
(
w
∗
x
i
+
b
)
L(w, b) = -\sum_{x_i \in M}{y_{i}(w*x_{i} + b)}
L(w,b)=−xi∈M∑yi(w∗xi+b)(不考虑
1
∥
w
∥
\frac{1}{\Vert w \Vert}
∥w∥1)
其中 M 为误分类点的集合,此损失函数为感知机学习的经验风险函数。
显然,损失函数非负,误分类点越少,误分类点距超平面越近,损失函数越小。
感知机学习策略是在假设空间中选取使基于误分类的损失函数最小的模型参数 w , b w,b w,b
算法
优化算法利用随机梯度下降法(Stochastic Gradient Descent)对损失函数进行极小化
输入:训练集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … } , ( x N , y N ) , 其 中 x i ∈ X = R n , y ∈ Y = { + 1 , − 1 } , i = 1 , 2 , … , N ; 学 习 率 η ( 0 ⩽ η ⩽ 1 ) T = \{ (x_1,y_1),(x_2,y_2),\ldots\} ,(x_N,y_N),其中x_i \in X = R^n,y\in Y = \{ +1,-1\},i =1,2,\ldots ,N;学习率\eta (0 \leqslant \eta \leqslant 1) T={(x1,y1),(x2,y2),…},(xN,yN),其中xi∈X=Rn,y∈Y={+1,−1},i=1,2,…,N;学习率η(0⩽η⩽1)
输出: w , b w,b w,b;感知机模型 f ( x ) = s i g n ( w ∗ x + b ) f(x) = sign(w*x + b) f(x)=sign(w∗x+b)
(1)任意选取一个超平面 w 0 , b 0 w_0,b_0 w0,b0,
(2)随机抽取一个实例点( x i , y i x_i,y_i xi,yi),
(3)当实例点被误分类( y i ( w ⋅ x i + b ) ⩽ 0 y_i(w \cdot x_i + b)\leqslant 0 yi(w⋅xi+b)⩽0),即位于分离超平面的错误侧,则调整w, b的值,使分离超平面向该误分类点的一侧移动,直至误分类点被正确分类
w = w + η y i x i w = w + \eta y_{i}x_{i} w=w+ηyixi
b = b + η y i b = b + \eta y_{i} b=b+ηyi
(4)转至(2),直至训练集没有误分类点
感知机学习算法由于采用不同的初值或选取不同的误分类点,解可以不同
拿出iris数据集中两个分类的数据和[sepal length,sepal width]作为特征
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline
from pandas import set_option
set_option("precision",3) #设置展示精度(小数点后3位)
from pandas import option_context
# load data
iris = load_iris() #下载数据
df = pd.DataFrame(iris.data[:100,:2], columns=iris.feature_names[:2]) #将数据类型转化为数据框
df['label'] = iris.target[:100] #将iris中的目标值赋到df的'label'列
#print(iris)
#展示数据
df.columns = ['sepal length', 'sepal width', 'label']
#print(df.shape)
#print(df.head())
#显示数据的数值类型
print(df.dtypes)
#计算标签值情况
print(df.label.value_counts())
#数据分布
#print(df.groupby('label').size()) #返回某一列的排序,以及相同元素的个数,这里鸢尾花的数据分布非常平衡
sepal length float64
sepal width float64
label int32
dtype: object
1 50
0 50
Name: label, dtype: int64
df.skew(axis = 0) #axis{index(0),columns(1)},定义计算的是列还是行
sepal length 0.415
sepal width 0.166
label 0.000
dtype: float64
#描述性统计的基本信息
df.describe()
sepal length | sepal width | label | |
---|---|---|---|
count | 100.000 | 100.000 | 100.000 |
mean | 5.471 | 3.099 | 0.500 |
std | 0.642 | 0.479 | 0.503 |
min | 4.300 | 2.000 | 0.000 |
25% | 5.000 | 2.800 | 0.000 |
50% | 5.400 | 3.050 | 0.500 |
75% | 5.900 | 3.400 | 1.000 |
max | 7.000 | 4.400 | 1.000 |
箱线图
sepal = pd.DataFrame(np.array(df.iloc[:,0:2]))
sepal.columns = ['sepal length', 'sepal width']
plt.figure(figsize=(15, 5))
plt.subplot(131)
box = sepal[:50].boxplot(return_type = "axes")
plt.subplot(132)
box = sepal[50:100].boxplot(return_type = "axes")
plt.subplot(133)
box = sepal[:100].boxplot(return_type = "axes")
箱线图
# 直方图
plt.figure(figsize=(8, 8))
plt.subplot(231)
df["sepal length"].hist()
plt.title('sepal length')
plt.subplot(232)
df["sepal width"].hist()
plt.title('sepal width')
plt.subplot(233)
df["label"].hist()
plt.title('label')
#密度图
plt.subplot(234)
df["sepal length"].plot(kind = "density", subplots = True, sharex = False)
plt.subplot(235)
df["sepal width"].plot(kind = "density", subplots = True, sharex = False)
plt.subplot(236)
df["label"].plot(kind = "density", subplots = True, sharex = False)
概率密度图
# #散点矩阵图
# from pandas.plotting import scatter_matrix
# scatter_matrix(df)
# plt.figure(figsize=(8,4))
# plt.subplot(121)
# plt.boxplot(df["sepal length"], labels=['sepal length'])
# plt.title("sepal length")
# plt.subplot(122)
# plt.boxplot(df["sepal width"], labels=['sepal width'])
# plt.title("sepal width")
Shapiro-Wilk检验
from scipy import stats
print(stats.shapiro(df["sepal length"]))
#Shapiro-Wilk检验,,第一个参数为w,表示接近正态分布的程度,越接近1,越服从正态,第二个参数为p,远大于0.05,说明数据不能拒绝原假设,即数据服从正态
print(stats.shapiro(df["sepal width"]))
(0.9696429371833801, 0.020757609978318214)
(0.9897727370262146, 0.6462364196777344)
数据预处理之无量纲化
#标准化后的数据均值趋近于零,右偏
se_l = np.array(df.iloc[:, 0:2])
se_l_stdscale =(se_l-np.mean(se_l))/np.std(se_l)
se_l_stdscale = pd.DataFrame(se_l_stdscale)
se_l_stdscale.columns = ['sepal length stander_scale','sepal width stander_scale']
# set_option("precision",3)
print(se_l_stdscale.skew(axis = 0))
print(stats.shapiro(se_l_stdscale))
with option_context('float_format', '{:f}'.format):
print(se_l_stdscale.describe())
# se_l_stdscale.describe()
sepal length stander_scale 0.42
sepal width stander_scale 0.17
dtype: float64
(0.9373731017112732, 1.362349735245516e-07)
sepal length stander_scale sepal width stander_scale
count 100.000000 100.000000
mean 0.903300 -0.903300
std 0.488740 0.364624
min 0.011425 -1.740337
25% 0.544569 -1.131029
50% 0.849223 -0.940620
75% 1.230041 -0.674047
max 2.067840 0.087588
#归一化后,将数据调整到某一范围(0到1),依然右偏
se_l = np.array(df.iloc[:, 0:2])
se_l_minmaxscale =(se_l-np.min(se_l))/(np.max(se_l)-np.min(se_l))
se_l_minmaxscale = pd.DataFrame(se_l_minmaxscale)
se_l_minmaxscale.columns = ['sepal length minmaxscale','sepal width minmaxscale']
set_option("precision",3)
print(se_l_minmaxscale.skew(axis = 0))
se_l_minmaxscale.describe()
sepal length minmaxscale 0.415
sepal width minmaxscale 0.166
dtype: float64
sepal length minmaxscale | sepal width minmaxscale | |
---|---|---|
count | 100.000 | 100.000 |
mean | 0.694 | 0.220 |
std | 0.128 | 0.096 |
min | 0.460 | 0.000 |
25% | 0.600 | 0.160 |
50% | 0.680 | 0.210 |
75% | 0.780 | 0.280 |
max | 1.000 | 0.480 |
数据正规化(data normalization)是将数据的每个样本(向量)变换为单位范数的向量,各样本之间是相互独立的.其实际上,是对向量中的每个分量值除以正规化因子.常用的正规化因子有 L1, L2 和 Max.
#正规化或正则化
se_l = np.array(df.iloc[:, 0:2])
se_l_normalize =[a/np.linalg.norm(se_l, ord=2) for a in se_l]#se_l/np.linalg.norm(se_l, ord=2)
se_l_normalize = pd.DataFrame(se_l_normalize)
se_l_normalize.columns = ['sepal length se_l_normalize','sepal width se_l_normalize']
set_option("precision",2)
print(se_l_normalize.skew(axis = 0))
se_l_normalize.describe()
sepal length se_l_normalize 0.42
sepal width se_l_normalize 0.17
dtype: float64
sepal length se_l_normalize | sepal width se_l_normalize | |
---|---|---|
count | 100.00 | 1.00e+02 |
mean | 0.09 | 4.91e-02 |
std | 0.01 | 7.58e-03 |
min | 0.07 | 3.17e-02 |
25% | 0.08 | 4.44e-02 |
50% | 0.09 | 4.83e-02 |
75% | 0.09 | 5.39e-02 |
max | 0.11 | 6.97e-02 |
data = np.array(df.iloc[:, :]) #.iloc 第一个参数是行索引(0到99行),第二个参数是列索引(0、1和最后一列)
X, y = data[:,:-1], data[:,-1]
y = np.array([1 if i == 1 else -1 for i in y]) #把值为“1”的标签定义为“1”,值为“0”的标签定义为“1”
Perceptron
# 数据线性可分,二分类数据
# 此处为一元一次线性方程
class Model:
def __init__(self):
self.w = np.ones(len(data[0])-1, dtype= np.float32) #定义了初始的w数组,所有元素都为1,第一个参数表示长度,第二个参数表示数据类型
self.b = 0 #定义了初始的b=0
self.l_rate = 0.1 #定义学习率=0.1
# self.data = data
def sign(self, x, w, b):
y = np.dot(x, w) + b #np.dot 矩阵的乘积
return y
# 随机梯度下降法
def fit(self, X_train, y_train):
is_wrong = False
i= 0
while not is_wrong:
wrong_count = 0 #计算误分类次数
for d in range(len(X_train)):
X = X_train[d]
y = y_train[d]
if y * self.sign(X, self.w, self.b) <= 0: #判断是否误分类
self.w = self.w + self.l_rate*np.dot(y, X) #对参数w迭代
self.b = self.b + self.l_rate*y #对参数b迭代
wrong_count += 1
if wrong_count == 0: #如果循环后,误分类次数为0,说明此时模型为分离超平面
is_wrong = True
else:
i += 1
return 'Perceptron Model!',i
# def score(self,X_test, y_test):
# count = 0
# for x,y in X_test,y_test:
# y_hat = -(fit.self.w[0]*x + fit.self.b)/fit.self.w[1]
# if y_hat == y:
# count += 1
# return count/len(X_train)
perceptron = Model()
perceptron.fit(X, y)
('Perceptron Model!', 678)
x_points = np.linspace(4, 7,100)
y_ = -(perceptron.w[0]*x_points + perceptron.b)/perceptron.w[1] #求得分离超平面
plt.plot(x_points, y_)
print("w: %.2f,%.2f"%(perceptron.w[0],perceptron.w[1]))
print("b:%.2f"%perceptron.b)
plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='-1')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
w: 7.80,-10.00
b:-12.10
感知机学习算法的对偶形式
将 w w w和 b b b表示为实例 x i x_i xi和标记 y i y_i yi的线性组合的形式,通过求解其系数而求得 w , b w, b w,b。
假设初始值
w
0
,
b
0
w_0, b_0
w0,b0均为0,对误分类点
(
x
i
,
y
i
)
(x_i, y_i)
(xi,yi),通过
w
←
w
+
η
y
i
x
i
w \leftarrow w + \eta y_i x_i
w←w+ηyixi
b
←
b
+
η
y
i
b \leftarrow b + \eta y_i
b←b+ηyi
逐步修改
w
,
b
w, b
w,b,假设修改
n
n
n次,则
w
,
b
w, b
w,b可分别表示为:
w
=
∑
i
=
1
N
α
i
y
i
x
i
w= \sum_{i=1}^{N} \alpha_i y_i x_i
w=i=1∑Nαiyixi
b
=
∑
i
=
1
N
α
i
y
i
b= \sum_{i=1}^{N} \alpha_i y_i
b=i=1∑Nαiyi
每个实例点对应有一个
α
i
\alpha_i
αi满足
α
i
≥
0
\alpha_i \geq 0
αi≥0且当
η
=
1
\eta = 1
η=1时,
α
i
\alpha_i
αi就表示第
i
i
i个实例点由于误分类而进行更新的次数。
对偶形式算法
输入:线性可分的数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) } T= \lbrace (x_1, y_1), (x_2, y_2),…,(x_N, y_N) \rbrace T={(x1,y1),(x2,y2),…,(xN,yN)},其中 x i ∈ R n x_i \in R^n xi∈Rn, y i ∈ { + 1 , − 1 } y_i \in \lbrace +1, -1 \rbrace yi∈{+1,−1}, i = 1 , 2 , 3 … , N i=1, 2, 3…, N i=1,2,3…,N,学习率 η ( 0 < η ≤ 1 ) \eta (0< \eta \leq 1) η(0<η≤1)
输出: α , b \alpha, b α,b;感知机模型 f ( x ) = s i g n ( ∑ j = 1 N α j y j x j ⋅ x + b ) f(x) = sign(\sum_{j=1}^{N} \alpha_j y_j x_j \cdot x + b) f(x)=sign(∑j=1Nαjyjxj⋅x+b),其中 α = ( a l p l a 1 , a l p l a 2 , … , a l p l a N ) T \alpha=(alpla_1, alpla_2,…,alpla_N)^T α=(alpla1,alpla2,…,alplaN)T
(1): α ← 0 \alpha \leftarrow 0 α←0, b ← 0 b \leftarrow 0 b←0
(2): 计算所有样本内积形成的Gram矩阵 G G G,
G = [ x i ⋅ x j ] N × N G=[x_i \cdot x_j ]_{N \times N} G=[xi⋅xj]N×N
(3): 在训练集中选取数据 ( x i , y i ) (x_i, y_i) (xi,yi),若
y i ( ∑ j = 1 N α j y j x j ⋅ x i + b ) ≤ 0 y_i (\sum_{j=1}^{N} \alpha_j y_j x_j \cdot x_i + b) \leq 0 yi(j=1∑Nαjyjxj⋅xi+b)≤0
(计算过程中可通过查 G G G的值来提高效率)则更新:
α i ← α i + η \alpha_i \leftarrow \alpha_i + \eta αi←αi+η
b ← b + η y i b \leftarrow b + \eta y_i b←b+ηyi
(4): 转至(3)直至没有误分类数据
对偶形式中,训练实例以内积的形式出现,提前将内积计算出来,用的时候可直接调用,降低了运算的时间复杂度,对于高维数据来说效果比较好
y = np.array([[1] if i == 1 else [-1] for i in y])
class Model2:
def __init__(self, x, y):
self.x = x
self.y = y
self.alpha = np.zeros((self.x.shape[0], 1)) #x.shape[0],表示x的行数;x.shape[1],表示x的列数,np.zeros中参数表示矩阵的形状
self.b = 0.0 # 偏置项
self.rate = 1 # 改变此处可以得到不同的平面
# 创建gram矩阵
self.g = np.zeros((self.x.shape[0], self.x.shape[0])) #创建了n行n列的矩阵
for i in range(x.shape[0]):
for j in range(x.shape[0]):
self.g[i][j] = np.dot(x[i:], x[j:].T)[0][0] #x[j:].T表示矩阵的转置
def fit(self):
length = self.x.shape[0]
while True:
count = 0 # 记录误分类点的数目
for i in range(length):
# 对矩阵进行运算
y = np.dot(self.g[i], self.alpha * self.y) + self.b
# 如果是小于0误分类点, 等于0 恰好在平面上
if y * [self.y[i]] <= 0:
self.alpha[i] = self.alpha[i] + self.rate
self.b = self.b + self.rate * self.y[i]
count += 1
if count == 0:
return np.sum(self.x * self.alpha * self.y, axis=0), self.b
#xArray = np.array([[3, 3], [4, 3], [1, 1]])
#yArray = np.array([[1], [1], [-1]])
# [[3 3]
# [4 3]
# [1 1]]
p = Model2(X, y)
w, b = p.fit()
print("w: %.2f,%.2f"%(w[0],w[1]))
print("b:%.2f"%b)
x_points = np.linspace(4, 7,100)
y_ = -(w[0]*x_points + b)/w[1] #求得分离超平面
plt.plot(x_points, y_)
plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='-1')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
w: 79.00,-100.70
b:-124.00
利用sklearn.linear_model.Perceptron训练感知机模型
from sklearn.linear_model import Perceptron
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import numpy as np
#下载数据
iris = load_iris()
X = iris.data[:100,0:2]
y = iris.target[:100]
y = np.array([1 if i == 1 else -1 for i in y])
#分离评估数据
seed= 7 #随机种子,为了固定随机数
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state = seed)
#展示数据
X1_train = pd.DataFrame(X_train,columns=iris.feature_names[0:2])
#展示数据
X1_train.columns = ['sepal length', 'sepal width'] #'sepal length', 'sepal width', 'petal width'
print(X1_train.shape)
print(X1_train.head())
(70, 2)
sepal length sepal width
0 6.7 3.1
1 6.5 2.8
2 5.2 3.5
3 6.6 2.9
4 5.5 4.2
print(X1_train.skew())
X1_train.describe()
sepal length 0.39
sepal width 0.19
dtype: float64
sepal length | sepal width | |
---|---|---|
count | 70.00 | 70.00 |
mean | 5.45 | 3.04 |
std | 0.60 | 0.50 |
min | 4.40 | 2.00 |
25% | 5.00 | 2.70 |
50% | 5.40 | 3.00 |
75% | 5.80 | 3.40 |
max | 6.80 | 4.20 |
# plt.figure(figsize=(5,5))
# #直方图
# X1_train.hist()
# #概率密度图
# X1_train.plot(kind = "density", subplots = True, sharex = False)
#k折交叉验证,k =5
num_folds = 5
seed = 7
scoring = "accuracy"
result = []
kfold = KFold(n_splits = num_folds, random_state = seed)
cv_results = cross_val_score(Perceptron(), X_train , y_train , cv = kfold, scoring = scoring)
result.append(cv_results)
print('Accuracy: %.2f(%f)' %(cv_results.mean(),cv_results.std()))
Accuracy: 0.94(0.083299)
clf = Perceptron(fit_intercept=False, n_iter=1000, shuffle=False)
clf.fit(X_train , y_train) #拟合SGD(随机梯度下降)的线性模型
clf.score(X_test, y_test) #给定测试数据集标签的平均精度
0.9
# 权重
print("w: %.2f,%.2f"%(clf.coef_[0][0],clf.coef_[0][1]))
# 截距
print("b: %.2f"%clf.intercept_)
w: 50.60,-94.50
b: 0.00
x_ponits = np.arange(4, 8)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)
plt.plot(data[:50, 0], data[:50, 1], 'bo', color='blue', label='-1')
plt.plot(data[50:100, 0], data[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
数据调整之后
from sklearn.preprocessing import StandardScaler,MinMaxScaler,Normalizer
#数据标准化缩放
sc_X = StandardScaler() #通过删除均值和缩放到单位方差来标准化特征
# sc_X = MinMaxScaler() #将属性缩放到一个指定的范围(通常是1-0)之间
# sc_X = Normalizer() #将每个样本缩放到单位范数(每个样本的范数为1),一般用于文本分类和聚类
X_ = sc_X.fit_transform(X)
X_train_std = sc_X.fit_transform(X_train)
X_test_std = sc_X.fit_transform(X_test)
X1_train_std = pd.DataFrame(X_train_std,columns=iris.feature_names[0:2])
#展示数据
X1_train_std.columns = ['sepal length', 'sepal width'] #'sepal length', 'sepal width','petal width'
print(X1_train_std.shape)
print(X1_train_std.head())
(70, 2)
sepal length sepal width
0 2.09 0.11
1 1.75 -0.49
2 -0.41 0.91
3 1.92 -0.29
4 0.09 2.31
# set_option("precision",3)
with option_context('float_format', '{:f}'.format):
print(X1_train_std.describe())
print(X1_train_std.skew())
sepal length sepal width
count 70.000000 70.000000
mean -0.000000 0.000000
std 1.007220 1.007220
min -1.749186 -2.091399
25% -0.748290 -0.689504
50% -0.081025 -0.088691
75% 0.586240 0.712392
max 2.254401 2.314558
sepal length 0.39
sepal width 0.19
dtype: float64
# plt.figure(figsize=(5,5))
# #直方图
# X1_train_std.hist()
# #概率分布图
# X1_train_std.plot(kind = "density", subplots = True, sharex = False)
#k折交叉验证,k =5
num_folds = 5
seed = 7
scoring = "accuracy"
result = []
kfold = KFold(n_splits = num_folds, random_state = seed)
cv_results = cross_val_score(Perceptron(), X1_train_std , y_train , cv = kfold, scoring = scoring)
result.append(cv_results)
print('Accuracy: %.2f(%f)' %(cv_results.mean(),cv_results.std()))
Accuracy: 0.99(0.028571)
标准化之后得到的训练模型平均准确率提高到0.99,而且标准差也降低了
clf = Perceptron(fit_intercept=False, n_iter=1000, shuffle=False)
clf.fit(X_train_std , y_train) #拟合SGD(随机梯度下降)的线性模型
clf.score(X_test_std, y_test) #给定测试数据集标签的平均精度
1.0
标准化之后得到的测试模型平均精度为1.0
# 权重
print(clf.coef_)
# 截距
print(clf.intercept_)
[[ 2.75484955 -2.89248187]]
[0.]
x_ponits = np.arange(-2, 4)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)
plt.plot(X_[:50, 0],X_[:50, 1], 'bo', color='blue', label='-1')
plt.plot(X_[50:100, 0], X_[50:100, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
在 X X X 特征为sepal length、 sepal width时
5折交叉验证
- | 平均准确率 | 标准差 | 测试准确率 |
---|---|---|---|
没有标准化 | 0.94 | 0.083299 | 0.9 |
Z-0 score | 0.99 | 0.028571 | 1.0 |
归一化 | 0.94 | 0.083299 | 1.0 |
正则化 | 0.99 | 0.028571 | 0.967 |
10折交叉验证
- | 平均准确率 | 标准差 | 测试准确率 |
---|---|---|---|
没有标准化 | 0.93 | 0.131708 | 0.9 |
Z-0 score | 0.99 | 0.042857 | 1.0 |
归一化 | 0.96 | 0.065465 | 1.0 |
正则化 | 0.97 | 0.057143 | 0.967 |
K值的选取会影响bias和viriance。K越大,每次投入的训练集的数据越多,模型的Bias越小。但是K越大,又意味着每一次选取的训练集之前的相关性越大,而这种大相关性会导致最终的test error具有更大的Variance。一般来说,根据经验我们一般选择k=5或10
分层抽取数据
参数 n_splits是将训练数据分成train/test对的组数,可根据需要进行设置,默认为10
参数test_size和train_size是用来设置train/test对中train和test所占的比例
参数 random_state控制是将样本随机打乱
#分层抽取数据,做分析
X2_train = np.concatenate((X[:35],X[50:85]))
X2_test = np.concatenate((X[35:50],X[85:]))
y2_train = np.concatenate((y[:35],y[50:85]))
y2_test = np.concatenate((y[35:50],y[85:]))
X2_train = pd.DataFrame(X2_train,columns=iris.feature_names[0:2])
#展示数据
X2_train.columns = ['sepal length', 'sepal width'] #'sepal length', 'sepal width', 'petal width'
print(X2_train.shape)
# print(X2_train.head())
print(X1_train_std.skew())
X2_train.describe()
(70, 2)
sepal length 0.390
sepal width 0.194
dtype: float64
sepal length | sepal width | |
---|---|---|
count | 70.000 | 70.000 |
mean | 5.527 | 3.119 |
std | 0.664 | 0.494 |
min | 4.300 | 2.000 |
25% | 5.000 | 2.800 |
50% | 5.450 | 3.100 |
75% | 6.000 | 3.400 |
max | 7.000 | 4.400 |
#直方图
X2_train.hist()
#概率分布图
X2_train.plot(kind = "density", subplots = True, sharex = False)
直方图
概率密度图
#k折交叉验证,k =5
num_folds = 5
seed = 7
scoring = "accuracy"
result = []
kfold = KFold(n_splits = num_folds, random_state = seed)
cv_results = cross_val_score(Perceptron(), X2_train , y2_train , cv = kfold, scoring = scoring)
result.append(cv_results)
print('Accuracy: %.2f(%f)' %(cv_results.mean(),cv_results.std()))
Accuracy: 1.00(0.000000)
clf = Perceptron(fit_intercept=False, n_iter=1000, shuffle=False)
clf.fit(X2_train , y2_train) #拟合SGD(随机梯度下降)的线性模型
clf.score(X2_test, y2_test) #给定测试数据集标签的平均精度
D:\anaconda\lib\site-packages\sklearn\linear_model\stochastic_gradient.py:152: DeprecationWarning: n_iter parameter is deprecated in 0.19 and will be removed in 0.21. Use max_iter and tol instead.
DeprecationWarning)
D:\anaconda\lib\site-packages\sklearn\utils\validation.py:761: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
y = column_or_1d(y, warn=True)
0.9666666666666667
# 权重
print(clf.coef_)
# 截距
print(clf.intercept_)
[[ 3. -5.2]]
[0.]
x_ponits = np.arange(4, 8)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)
plt.plot(data[:35, 0], data[:35, 1], 'bo', color='blue', label='train(-1)')
plt.plot(data[50:85, 0], data[50:85, 1], 'bo', color='orange', label='train(1)')
plt.plot(data[35:50, 0], data[35:50, 1], 'b+', color='red', label='test(-1)')
plt.plot(data[85:, 0], data[85:, 1], 'b+', color='green', label='test(1)')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
参考文献:
【1】李航.统计学习方法
【2】github https://github.com/wzyonggege/statistical-learning-method/blob/master/Perceptron/Iris_perceptron.ipynb