赞
踩
传统机器学习适合结构化数据
深度学习适合处理非结构化数据(图像,音频,视频,文本)
目录
z为净输入,是连续的值,通过激励函数转成离散的值
感知器是一个自学习算法,即可以根据输入的数据(样本),不断调整权重的更新,最终完成分类。权重的更新公式如下:
其中,j表示某一列,i表示某一个样本。学习率 y(hat)代表y预测值
感知器的权重更新依据是:如果预测准确,则权重不进行更新,否则,增加权重,使其更趋向于正确的类别。
说明:
参考之前感知器的实现步骤,使用感知器实现与门与或门的计算。
- import numpy as np
- # 定义数据集
- X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
- # 定义标签(每个样本所属的分类)。
- y = np.array([0, 0, 0, 1])
- # 定义权重。对于单层感知器,权重通常初始化为0或者很小的数值。
- # w = np.zeros(3)
- w = np.random.random(3)
- # 定义学习率。
- eta = 0.1
-
- for epoch in range(7):
- for x, target in zip(X, y):
- # 计算净输入
- z = np.dot(w, x)
- # 根据净输入,计算分类值。
- y_hat = 1 if z >= 0 else 0
- # 根据预测值与真实值,进行权重调整。
- w = w + eta * (target - y_hat) * x
- # 注意数组的矢量化计算,相当于执行了以下的操作。
- # w[0] = w[0] + eta * (y - y_hat) * x[0]
- # w[1] = w[1] + eta * (y - y_hat) * x[1]
- # w[2] = w[2] + eta * (y - y_hat) * x[2]
- print(target, y_hat)
- print(w)
算法的Python实现
现在,我们使用Python语言来实现感知器算法,进行鸢尾花的分类
- class Perceptron:
- """通过Python语言实现感知器类。用来进行二分类任务。"""
-
- def __init__(self, eta, epoch):
- """初始化方法。
-
- Parameter:
- -------
- eta: float
- 学习率。
- epoch: int
- 对训练集训练的轮数。
- """
- self.eta = eta
- self.epoch = epoch
-
- def step(self, z):
- """阶跃函数。对净输入进行转换。
-
- Parameter:
- -----
- z: 标量或数组类型
- 净输入。
-
- Return:
- ------
- t: 变量或数组类型。
- 分类的结果。0或者1。当z >= 0时,返回1,否则返回0。
- """
- # return 1 if z >= 0 else 0
- return np.where(z >= 0, 1, 0)
-
- def fit(self, X, y):
- """训练方法。
-
- Parameter:
- X: 类数组类型。形状为 (样本数量, 特征数量)
- 提供的训练集。
- y: 类数组类型。形状为(样本数量,)
- 样本对应的标签(分类)
- """
- # 对类型进行转换,不管是什么二维类型,统一转换成二维的ndarray数组类型。
- X = np.asarray(X)
- y = np.asarray(y)
- # 注意:权重的数量要比特征的数量多1。多出来的一个就是偏置。
- self.w_ = np.zeros(X.shape[1] + 1)
- # 定义损失列表。用来存放每个epoch迭代之后,分类错误的数量。
- self.loss_ = []
- # 迭代epoch指定的轮数。
- for i in range(self.epoch):
- # 用来记录单次epoch的损失值(分类错误的数量)
- loss = 0
- for x, target in zip(X, y):
- # 计算净输入
- z = np.dot(x, self.w_[1:]) + self.w_[0]
- # 根据净输入,计算分类。
- y_hat = self.step(z)
- # if target != y_hat:
- # loss += 1
- loss += target != y_hat
- # 调整权重
- self.w_[1:] += self.eta * (target - y_hat) * x
- # 调整偏置
- self.w_[0] += self.eta * (target - y_hat)
- # 将损失值加入到损失列表当中。
- self.loss_.append(loss)
-
- def predict(self, X):
- """预测方法。根据提供的数据集X,返回每一个样本对应的标签(分类)。
-
- Parameter:
- -----
- X: 类数组类型。形状为 (样本数量, 特征数量)
- 提供预测集。
-
- Return:
- -----
- label: 类数组类型。形状为:(样本数量,)
- 预测的每一个便签分类。
- """
- X = np.asarray(X)
- # 计算净输入。(矢量化计算,没有使用循环分别对每一个样本求净输出)
- z = np.dot(X, self.w_[1:]) + self.w_[0]
- # 获取最终的分类结果。(一维数组类型。)
- result = self.step(z)
- return result
- # 感知器类进行测试。
- X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
- y = np.array([0, 0, 0, 1])
- p = Perceptron(0.1, 7)
- p.fit(X, y)
- print(p.w_)
- print(p.loss_)
练习
- class Perceptron:
- """通过Python语言实现感知器类。用来进行二分类任务。"""
-
- def __init__(self, eta, epoch):
- """初始化方法。
-
- Parameter:
- -------
- eta: float
- 学习率。
- epoch: int
- 对训练集训练的轮数。
- """
- self.eta = eta
- self.epoch = epoch
-
- def step(self, z):
- """阶跃函数。对净输入进行转换。
-
- Parameter:
- -----
- z: 标量或数组类型
- 净输入。
-
- Return:
- ------
- t: 变量或数组类型。
- 分类的结果。0或者1。当z >= 0时,返回1,否则返回0。
- """
- # return 1 if z >= 0 else 0
- return np.where(z >= 0, 1, 0)
-
- def fit(self, X, y):
- """训练方法。
-
- Parameter:
- X: 类数组类型。形状为 (样本数量, 特征数量)
- 提供的训练集。
- y: 类数组类型。形状为(样本数量,)
- 样本对应的标签(分类)
- """
- # 对类型进行转换,不管是什么二维类型,统一转换成二维的ndarray数组类型。
- X = np.asarray(X)
- y = np.asarray(y)
- # 注意:权重的数量要比特征的数量多1。多出来的一个就是偏置。
- self.w_ = np.zeros(X.shape[1] + 1)
- # 定义损失列表。用来存放每个epoch迭代之后,分类错误的数量。
- self.loss_ = []
- # 迭代epoch指定的轮数。
- for i in range(self.epoch):
- # 用来记录单次epoch的损失值(分类错误的数量)
- loss = 0
- for x, target in zip(X, y):
- # 计算净输入
- z = np.dot(x, self.w_[1:]) + self.w_[0]
- # 根据净输入,计算分类。
- y_hat = self.step(z)
- # if target != y_hat:
- # loss += 1
- loss += target != y_hat
- # 调整权重
- self.w_[1:] += self.eta * (target - y_hat) * x
- # 调整偏置
- self.w_[0] += self.eta * (target - y_hat)
- # 将损失值加入到损失列表当中。
- self.loss_.append(loss)
-
- def predict(self, X):
- """预测方法。根据提供的数据集X,返回每一个样本对应的标签(分类)。
-
- Parameter:
- -----
- X: 类数组类型。形状为 (样本数量, 特征数量)
- 提供预测集。
-
- Return:
- -----
- label: 类数组类型。形状为:(样本数量,)
- 预测的每一个便签分类。
- """
- X = np.asarray(X)
- # 计算净输入。(矢量化计算,没有使用循环分别对每一个样本求净输出)
- z = np.dot(X, self.w_[1:]) + self.w_[0]
- # 获取最终的分类结果。(一维数组类型。)
- result = self.step(z)
- return result
- # 感知器类进行测试。
- X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
- y = np.array([0, 0, 0, 1])
- p = Perceptron(0.1, 7)
- p.fit(X, y)
- print(p.w_)
- print(p.loss_)
- # 使用感知器实现鸢尾花的分类。
- from sklearn.datasets import load_iris
- from sklearn.model_selection import train_test_split
- import pandas as pd
-
- # return_X_y设置为True,只返回Data与target。
- X, y = load_iris(return_X_y=True)
- # X.shape, y.shape
- # np.concatenate 合并的数组,要求具有相同的维度,因此,需要将y变成
- # 2维的形式。
- data = pd.DataFrame(np.concatenate((X, y.reshape((-1, 1))), axis=1))
- # np.sum(data.duplicated())
- # display(data.shape)
- data.drop_duplicates(inplace=True)
- # display(data.shape)
-
- # data[4].map({0:1, 1:-1, 2:2})
- # data = data[data[4] != 2]
- data[4] = data[4].map({0:10, 1:0, 2:1})
- data = data[data[4] != 10]
- data[4].value_counts()
- # data[4].value_counts()
-
- X, y = data.iloc[:, :4], data.iloc[:, 4]
- train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.2, random_state=0)
- # train_X.shape, test_X.shape
- p = Perceptron(0.1, 20)
- p.fit(train_X, train_y)
- # 查看训练后的权重与损失情况。
- # display(p.w_)
- # display(p.loss_)
- result = p.predict(test_X)
- np.sum(test_y == result) / len(result)
-
- import matplotlib as mpl
- import matplotlib.pyplot as plt
- mpl.rcParams["font.family"] = "SimHei"
- mpl.rcParams["axes.unicode_minus"] = False
-
- plt.plot(test_y.values, "go", ms=15, label="真实值")
- plt.plot(result, "rx", ms=15, label="预测值")
- plt.title("感知器二分类预测")
- plt.xlabel("样本序号")
- plt.ylabel("样本类别")
- plt.legend()
- plt.show()
-
- # 绘制损失曲线。(每个epoch预测样本错误的数量)
- plt.plot(range(1, len(p.loss_) + 1), p.loss_, "o-")
使用Python实现train_test_split方法的功能
- split_index = test_size * len()
- data[:split_index]
- data[split_index:]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。