选择花萼长度 花瓣长度作为特征,使用梯度下降,求取和方差的最小值,使得误差最小
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib.colors import ListedColormap
#显示训练数据
def plot_decision_regions(x,y,classifier,resolution=0.02):
marker = ('s','x','o','v')
colors = ('red','blue','lightgreen','gray','cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])#np.unique 去除重复的数据
#获取花萼长度 花瓣长度的最小值和最大值
x1_min,x1_max = x[:,0].min()-1,x[:,0].max()
x2_min,x2_max = x[:,1].min()-1,x[:,1].max()
#向量转二维矩阵 矩阵行 矩阵列
# 输入的x,y,就是网格点的横纵坐标列向量(非矩阵) -----》 x,y组合成网格点
# 输出的X,Y,就是坐标矩阵
xx1,xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution),np.arange(x2_min,x2_max,resolution))#返回list,有两个元素,第一个元素是X轴的取值,第二个元素是Y轴的取值
z = classifier.predict(np.array([xx1.ravel(),xx2.ravel()]).T) #ravel()矩阵转数组
z = z.reshape(xx1.shape)
plt.contourf(xx1,xx2,z,alpha=0.4,cmap=cmap) #等高图
print(len(np.arange(x1_min,x1_max,resolution)))#185
print(len(np.arange(x2_min,x2_max,resolution)))#255
print('xx1shape:',xx1.shape) #(255, 185)
print('xx2shape:',xx2.shape) #(255, 185)
print('zshape:', z.shape) #(255, 185) [(x10,x20),(x11,x20),(x13,x20)...]
print(xx2)
print('z:',z)
plt.xlim(xx1.min(),xx1.max())
plt.ylim(xx2.min(),xx2.max())
print(np.unique(y)) #[-1,1]
#绘制训练数据的散点图
for idx,label in enumerate(np.unique(y)):
print(idx,label)
print(x)
plt.scatter(x=x[y == label,0],y = x[y == label,1],alpha=0.8,c=cmap(idx),marker=marker[idx],label=label)#x:特征1 y:特征2
class AdalineGD(object):
'''
eta float 学习效率 0-1 越小越精确
n_iter int 对训练数据进行学习改进次数
w_ 一维向量 权重数值
error_ 每次迭代改进时,网络对数据进行错误判断的次数
'''
def __init__(self,eta=0.01,n_iter=50):
self.eta = eta
self.n_iter = n_iter
def fit(self,X,y):
'''
X 二维数组 【n_sample,n_features】
n_sample X 中含有训练数据的条目
features 含有4个数据的一维向量,表示一条训练条目
y:一维向量 用于存贮每一训练条目对应的正确分类
y = w1*x1+w2*x2+W0*1
'''
self.w_ = np.zeros(1+X.shape[1])
self.const = [] #训练的次数
self.cost_ = [] #损失
for i in range(self.n_iter):
output = self.net_input(X) #输入数据加权 , 加w0
#output = w0 + w1*x1 + ... +wmxm
# print(output.shape)
# print(y.shape)
errors = (y - output) #预测值与标签的误差
self.w_[1:] += self.eta *X.T.dot(errors)
self.w_[0] += self.eta * errors.sum()
cost = (errors ** 2).sum()/2.0 #损失函数:误差平方和的均值
self.cost_.append(cost)
if cost > 5: #误差平方和的均值 >5,累计加一
if len(self.const) == 0:
self.const.append(1)
else:
self.const.append(self.const[-1]+1)
else:
if len(self.const) == 0:
self.const.append(1)
else:
self.const.append(self.const[-1])
#加权求和
def net_input(self,x):
return np.dot(x,self.w_[1:])+self.w_[0]
#激活函数
def activation(self,x):
return self.net_input(x)
#预测
def predict(self,x):
print('predict:',x)
return np.where(self.activation(x) >= 0 ,1,-1)
if __name__ == '__main__':
# 数据集 http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
# 花萼长度 花萼宽度 花瓣长度 花瓣宽度 类别(Iris Setosa(山鸢尾)、Iris Versicolour(杂色鸢尾)、Iris Virginica(维吉尼亚鸢尾))
#加载数据
file = './datasets/iris.data.txt'
df = pd.read_csv(file, header=None) # 第一行不是数据说明,是真实数据
df.head()
#提取特征数据,标签
y = df.loc[0:99, 4].values # 前100行的第5列
print('y:',y.shape)
print(y)
y = np.where(y == 'Iris-setosa', 1, -1) # np.where(条件, x, y) 条件为True,输出x,不满足输出y
x = df.iloc[0:100, [0, 2]].values # 获取花萼长度 花瓣长度特征
plt.scatter(x[:100, 0], x[:100, 1], color='red', marker='o', label='setosa') # marker形状 花萼长度为横轴,花瓣长度为纵轴
plt.xlabel('x1')
plt.ylabel('x2')
plt.xticks(rotation=45)#倾斜45
plt.title('训练数据')
plt.legend(loc='upper left')
#系统字体
# matplotlib.matplotlib_fname() # 将会获得matplotlib包所在文件夹
# 指定默认字体
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['font.family'] = 'sans-serif'
# 解决负号'-'显示为方块的问题
matplotlib.rcParams['axes.unicode_minus'] = False
plt.show()
#训练
ada = AdalineGD(eta=0.0001,n_iter=1000)
ada.fit(x,y) #训练
plot_decision_regions(x,y,classifier=ada) #classifier 分类器
plt.show()
# 错误的次数
plt.title('错误的次数')
plt.plot(range(1,len(ada.const)+1),ada.const,marker='o')
plt.show()
#误差平方和
plt.title('误差')
plt.plot(range(1,len(ada.cost_)+1),ada.cost_,marker='o')
plt.show()