如何在 Python 中创建一个简单的神经网络

news/2024/7/7 20:43:43

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

引言

在过去的几十年里,机器学习对世界产生了巨大的影响,而且它的普及程度似乎在不断增长。最近,越来越多的人已经熟悉了机器学习的子领域,如神经网络,这是由人类大脑启发的网络。在本文中,将介绍用于一个简单神经网络的 Python 代码,该神经网络对于一个 1x3 向量,分类第一个元素是否为 10。

步骤1: 导入 NumPy、 Scikit-learn 和 Matplotlib

import numpy as np
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt

我们将在这个项目中使用上述三个库。NumPy 将用于创建向量和矩阵以及数学操作。Scikit-learn 将用于缩放数据,Matplotlib 将用于在神经网络训练期间绘图。

步骤2: 创建一个训练和测试数据集

神经网络在大型和小型数据集的学习趋势方面都很擅长。然而,数据科学家必须意识到过拟合的危险,这在使用小数据集的项目中更为明显。过拟合是当一个算法训练和建模过于接近一组数据点,以至于它不能很好地推广到新的数据点。

通常情况下,过拟合的机器学习模型在训练的数据集上有很高的准确性,但是作为一个数据科学家,目标通常是尽可能精确地预测新的数据点。为了确保根据预测新数据点的好坏来评估模型,而不是根据对当前数据点的建模好坏来评估模型,通常将数据集拆分为一个训练集和一个测试集(有时是一个验证集)。

input_train = np.array([[0, 1, 0], [0, 1, 1], [0, 0, 0], [10, 0, 0], [10, 1, 1], [10, 0, 1]])
output_train = np.array([[0], [0], [0], [1], [1], [1]])
input_pred = np.array([1, 1, 0])input_test = np.array([[1, 1, 1], [10, 0, 1], [0, 1, 10], [10, 1, 10], [0, 0, 0], [0, 1, 1]])
output_test = np.array([[0], [1], [0], [1], [0], [0]])

在这个简单的神经网络中,我们将1x3向量分类,10作为第一个元素。使用 NumPy 的 array 函数创建输入和输出训练集和测试集,并创建 input_pred 以测试稍后将定义的 prediction 函数。训练和测试数据由6个样本组成,每个样本具有3个特征,由于输出已经给出,我们理解这是监督式学习的一个例子。

第三步: 扩展数据集

许多机器学习模型不能理解例如单位之间的区别,自然而然地对高度的特征应用更多的权重。这会破坏算法预测新数据点的能力。此外,训练具有高强度特征的机器学习模型将会比需要的慢,至少如果使用梯度下降法。这是因为当输入值在大致相同的范围内时,梯度下降法收敛得更快。

scaler = MinMaxScaler()
input_train_scaled = scaler.fit_transform(input_train)
output_train_scaled = scaler.fit_transform(output_train)
input_test_scaled = scaler.fit_transform(input_test)
output_test_scaled = scaler.fit_transform(output_test)

在我们的训练和测试数据集中,这些值的范围相对较小,因此可能没有必要进行特征扩展。然而,这样可以使得小伙伴们使用自己喜欢的数字,而不需要更改太多的代码。由于 Scikit-learn 包及其 MinMaxScaler 类,在 Python 中实现特征伸缩非常容易。只需创建一个 MinMaxScaler 对象,并使用 fit_transform 函数将非缩放数据作为输入,该函数将返回相同的缩放数据。Scikit-learn 包中还有其他缩放功能,我鼓励您尝试这些功能。

第四步: 创建一个神经网络类

要熟悉神经网络的所有元素,最简单的方法之一就是创建一个神经网络类。这样一个类应该包括所有的变量和函数,将是必要的神经网络工作正常。

class NeuralNetwork():def __init__(self, ):self.inputSize = 3self.outputSize = 1self.hiddenSize = 3self.W1 = np.random.rand(self.inputSize, self.hiddenSize)self.W2 = np.random.rand(self.hiddenSize, self.outputSize)self.error_list = []self.limit = 0.5self.true_positives = 0self.false_positives = 0self.true_negatives = 0self.false_negatives = 0def forward(self, X):self.z = np.matmul(X, self.W1)self.z2 = self.sigmoid(self.z)self.z3 = np.matmul(self.z2, self.W2)o = self.sigmoid(self.z3)return odef sigmoid(self, s):return 1 / (1 + np.exp(-s))def sigmoidPrime(self, s):return s * (1 - s)def backward(self, X, y, o):self.o_error = y - oself.o_delta = self.o_error * self.sigmoidPrime(o)self.z2_error = np.matmul(self.o_delta,np.matrix.transpose(self.W2))self.z2_delta = self.z2_error * self.sigmoidPrime(self.z2)self.W1 += np.matmul(np.matrix.transpose(X), self.z2_delta)self.W2 += np.matmul(np.matrix.transpose(self.z2),self.o_delta)def train(self, X, y, epochs):for epoch in range(epochs):o = self.forward(X)self.backward(X, y, o)self.error_list.append(np.abs(self.o_error).mean())def predict(self, x_predicted):return self.forward(x_predicted).item()def view_error_development(self):plt.plot(range(len(self.error_list)), self.error_list)plt.title('Mean Sum Squared Loss')plt.xlabel('Epoch')plt.ylabel('Loss')def test_evaluation(self, input_test, output_test):for i, test_element in enumerate(input_test):if self.predict(test_element) > self.limit and \output_test[i] == 1:self.true_positives += 1if self.predict(test_element) < self.limit and \output_test[i] == 1:self.false_negatives += 1if self.predict(test_element) > self.limit and \output_test[i] == 0:self.false_positives += 1if self.predict(test_element) < self.limit and \output_test[i] == 0:self.true_negatives += 1print('True positives: ', self.true_positives,'\nTrue negatives: ', self.true_negatives,'\nFalse positives: ', self.false_positives,'\nFalse negatives: ', self.false_negatives,'\nAccuracy: ',(self.true_positives + self.true_negatives) /(self.true_positives + self.true_negatives +self.false_positives + self.false_negatives))

步骤4.1: 创建一个 Initialize 函数

当我们在 Python 中创建一个类以便正确地初始化变量时,会调用 __init__ 函数。

def __init__(self, ):self.inputSize = 3self.outputSize = 1self.hiddenSize = 3self.W1 = torch.randn(self.inputSize, self.hiddenSize)self.W2 = torch.randn(self.hiddenSize, self.outputSize)self.error_list = []self.limit = 0.5self.true_positives = 0self.false_positives = 0self.true_negatives = 0self.false_negatives = 0

在这个例子中,我选择了一个有三个输入节点、三个隐藏层节点和一个输出节点的神经网络。以上的 __init__ 函数初始化描述神经网络大小的变量。inputSize 是输入节点的数目,它应该等于输入数据中特征的数目。outputSize 等于输出节点数,hiddenSize 描述隐藏层中的节点数。此外,我们的网络中不同节点之间的权重将在训练过程中进行调整。

除了描述神经网络的大小和权重的变量之外,我还创建了几个在创建神经网络对象时初始化的变量,这些对象将用于评估目的。误差列表将包含每个时期的平均绝对误差(MAE) ,这个极限将描述一个向量应该被分类为一个向量,元素10作为第一个元素而不是。然后,还有一些变量可以用来存储真实阳性、假阳性、真实阴性和假阴性的数量。

步骤4.2: 创建一个前向传播函数

前向传播函数的作用是通过神经网络的不同层次进行迭代,以预测特定 epoch 的输出。然后,根据预测输出和实际输出之间的差异,在反向传播的过程中更新权重。

def forward(self, X):self.z = np.matmul(X, self.W1)self.z2 = self.sigmoid(self.z)self.z3 = np.matmul(self.z2, self.W2)o = self.sigmoid(self.z3)return o

为了计算每一层中每个节点的值,前一层中节点的值将被乘以适当的权重,然后应用非线性激活函数来扩大最终输出函数的可能性。在这个例子中,我们选择了 Sigmoid 作为激活函数,但也有许多其他的选择。

步骤4.3: 创建一个反向传播函数

反向传播是对神经网络中不同节点的权值进行更新,从而决定其重要性的过程。

def backward(self, X, y, o):self.o_error = y - oself.o_delta = self.o_error * self.sigmoidPrime(o)self.z2_error = np.matmul(self.o_delta,np.matrix.transpose(self.W2))self.z2_delta = self.z2_error * self.sigmoidPrime(self.z2)self.W1 += np.matmul(np.matrix.transpose(X), self.z2_delta)self.W2 += np.matmul(np.matrix.transpose(self.z2),self.o_delta)

在上面的代码片段中,输出层的输出错误被计算为预测输出与实际输出之间的差值。然后,在重复整个过程直到到达输入层之前,将这个错误与 Sigmoid 相乘以运行梯度下降法。最后,更新不同层之间的权重。

步骤4.4: 创建一个训练函数

在训练过程中,该算法将运行向前和向后传递,从而更新每个 epoch 的权重。为了得到最精确的权重值,这是必要的。

def train(self, X, y, epochs):for epoch in range(epochs):o = self.forward(X)self.backward(X, y, o)self.error_list.append(np.abs(self.o_error).mean())

除了向前和向后传播之外,我们还将平均绝对误差(MAE)保存到一个错误列表中,以便日后观察平均绝对误差在训练过程中是如何演变的。

步骤4.5: 创建一个预测函数

在训练过程中对权重进行了微调之后,该算法就可以预测新数据点的输出。预测的输出数字有望与实际输出数字非常接近。

def predict(self, x_predicted):return self.forward(x_predicted).item()

步骤4.6: 绘制平均绝对误差发展图

评价机器学习算法质量的方法有很多。经常使用的测量方法之一是平均绝对误差,这个误差应该随着时间的推移而减小。

def view_error_development(self):plt.plot(range(len(self.error_list)), self.error_list)plt.title('Mean Sum Squared Loss')plt.xlabel('Epoch')plt.ylabel('Loss')

步骤4.7: 计算精度及其组成部分

真正、假正、真负和假负的数量描述了机器学习分类算法的质量。训练后的神经网络权值更新,使算法能够准确地预测新的数据点。在二进制分类任务中,这些新数据点只能是1或0。根据预测值是否高于或低于定义的限制,算法将新条目分为1或0。

def test_evaluation(self, input_test, output_test):for i, test_element in enumerate(input_test):if self.predict(test_element) > self.limit and \output_test[i] == 1:self.true_positives += 1if self.predict(test_element) < self.limit and \output_test[i] == 1:self.false_negatives += 1if self.predict(test_element) > self.limit and \output_test[i] == 0:self.false_positives += 1if self.predict(test_element) < self.limit and \output_test[i] == 0:self.true_negatives += 1print('True positives: ', self.true_positives,'\nTrue negatives: ', self.true_negatives,'\nFalse positives: ', self.false_positives,'\nFalse negatives: ', self.false_negatives,'\nAccuracy: ',(self.true_positives + self.true_negatives) /(self.true_positives + self.true_negatives +self.false_positives + self.false_negatives))

当运行 test _ evaluation 函数时,我们得到以下结果:

真正: 2

真负: 4

假正: 0

假负: 0

准确性由以下公式给出:

由此我们可以推断,在我们的案例中,精确度是1。

第五步: 运行一个脚本来训练和评估神经网络模型

NN = NeuralNetwork()
NN.train(input_train_scaled, output_train_scaled, 200)
NN.predict(input_pred)
NN.view_error_development()
NN.test_evaluation(input_test_scaled, output_test_scaled)

为了尝试我们刚刚构建的神经网络类,我们将首先初始化一个神经网络类型的对象。然后对训练数据进行神经网络训练,在新训练的模型在测试向量上进行测试之前,对算法的权值进行200个 epoch 以上的“修正”。然后,在利用测试数据集对模型进行评估之前,绘制误差图。

第六步: 改进脚本并使用它

提供的代码可以很容易地修改,以处理其他类似的情况。我们鼓励读者尝试改变变量并使用自己的数据等等。改进或变更的潜在想法包括但不限于:

  1. 泛化代码以适用于任何输入和输出大小的数据

  2. 使用平均绝对误差以外的另一个度量来衡量误差

  3. 使用其他的缩放函数

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目31讲

在「小白学视觉」公众号后台回复:Python视觉实战项目31讲即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

下载4:leetcode算法开源书

在「小白学视觉」公众号后台回复:leetcode即可下载。每题都 runtime beats 100% 的开源好书,你值得拥有!


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


http://lihuaxi.xjx100.cn/news/282045.html

相关文章

B站500万粉up主党妹被黑客勒索:交钱赎“人”!顶级安全专家:无解

郭一璞 十三 发自 凹非寺量子位 报道 | 公众号 QbitAI最近真是太难了&#xff0c;要防新冠病毒&#xff0c;还要防勒索病毒。昨天&#xff0c;B站556万粉丝的up主「机智的党妹」就发视频说&#xff0c;自己被勒索病毒攻击了。她正在制作的数百个GB的视频素材文件&#xff0c;全…

浅谈Android系统开发中LOG的使用【转】

本文转载自&#xff1a;http://blog.csdn.net/luoshengyang/article/details/6581828 在程序开发过程中&#xff0c;LOG是广泛使用的用来记录程序执行过程的机制&#xff0c;它既可以用于程序调试&#xff0c;也可以用于产品运营中的事件记录。在Android系统中&#xff0c;提供…

php网站怎么伪静态,php怎么实现网页伪静态

php实现网页伪静态的方法&#xff1a;首先在服务器根目录创建一个“.htaccess”文件&#xff1b;然后添加内容为“RewriteRule ^index-(\d)\.html$ index.php?id$1”即可。本文操作环境&#xff1a;Windows7系统、PHP7.1版&#xff0c;DELL G3电脑.htaccess实现php网站伪静态&…

Linux 使用者身份與群組記錄的檔案

在我們Linux系統當中&#xff0c;預設的情況下&#xff0c;所有的系統上的帳號與一般身份使用者&#xff0c;還有那個root的相關資訊&#xff0c; 都是記錄在/etc/passwd這個檔案內的。至於個人的密碼則是記錄在/etc/shadow這個檔案下。 此外&#xff0c;Linux所有的群組名稱都…

简单介绍Lua中三种循环语句的使用

今天小编就为大家分享一篇关于Lua中三种循环语句的使用讲解&#xff0c;小编觉得内容挺不错的&#xff0c;现在分享给大家&#xff0c;具有很好的参考价值&#xff0c;需要的朋友一起跟随小编来看看吧 Lua的循环和C语言的循环的语法其实差不多&#xff0c;所以&#xff0c;理解…

DeepMind、哈佛造出了 AI「小白鼠」,从跑、跳、觅食、击球窥探神经网络的奥秘...

机器之心报道机器之心编辑部我们可以用研究小白鼠的方式来研究 AI 吗&#xff1f;或许可以。在一篇 ICLR 2020 Spotlight 论文中&#xff0c;DeepMind 和哈佛大学的研究者构建了一个基于 AI 的虚拟小鼠&#xff0c;能够执行跑、跳、觅食、击球等多项复杂任务。他们还尝试用神经…

unix oracle控制台,Linux平台下启动oracle11gEM控制台

当我们的oracle服务器是使用的Linux/Unix系统时,我们从windows或者其他的客户端想用启动oracle的EM工具了解一些系统系统信息时可当我们的Oracle服务器是使用的Linux/Unix系统时,我们从windows或者其他的客户端想用启动oracle的EM工具了解一些系统系统信息时可以采用如下方式:首…

一次完整的从webshell到域控的探索之路

前言 内网渗透测试资料基本上都是很多大牛的文章告诉我们思路如何&#xff0c;但是对于我等小菜一直是云里雾里。 于是使用什么样的工具才内网才能畅通无阻&#xff0c;成了大家一直以来的渴求。 今天小菜我本着所有师傅们无私分享的精神&#xff0c;特将三年内求师傅&#xff…