《蜥蜴书》_讲义及源码解读_10
从生物神经元到人工神经元
生物神经元
Cell body 细胞体 | Nucleus 核 | axon 轴突 | axon hillock 轴突丘 |
---|---|---|---|
dendrite 树突 | telodendria 终树突 | synaptic terminals 突触终端 | Neurons 神经元 |
生物神经元:这是动物大脑中一种不太常见的细胞,包括:细胞体Cell body
(含有细胞核Nucleus
和大部分细胞组织),许多貌似树枝的树突dendrite
,和一条非常长的轴突axon
。轴突的长度可能是细胞体的几倍,也可能是一万倍。在轴突的末梢,轴突分叉成为终树突telodendria
,终树突的末梢是突触,突触连接着其它神经元的树突或细胞体。
生物神经元会产生被称为“动作电位”(或称为信号)的短促电脉冲,信号沿轴突传递,使突触释放出被称为神经递质的化学信号。当神经元在几毫秒内接收了足够量的神经递质,这个神经元也会发送电脉冲(事实上,要取决于神经递质,一些神经递质会禁止发送电脉冲)。
生物神经网络(BNN)如今仍是活跃的研究领域,人们通过绘制出了部分大脑的结构,发现神经元分布在连续的皮层上,尤其是在大脑皮质上(大脑外层)
神经元的逻辑计算
McCulloch
和 Pitts
提出了一个非常简单的生物神经元模型,它后来演化成了人工神经元:一个或多个二元(开或关)输入,一个二元输出。当达到一定的输入量时,神经元就会产生输出。
如下图,假设有两个活跃的输入时,神经元就被激活:
感知机
感知器是最简单的人工神经网络结构之一,由Frank Rosenblatt
发明于 1957 年。它基于一种稍微不同的人工神经元(如下图 ),阈值逻辑单元(TLU
),或称为线性阈值单元(LTU
):输入和输出是数字(而不是二元开/关值),并且每个输入都连接一个权重。TLU
计算其输入的加权和 (z=XTWz=X^T Wz=XTW),然后将阶跃函数应用于该和,并输出结果:hW(X)=step(XTW)h_W(X)=step(X^TW)hW(X)=step(XTW)
感知机最常用的阶跃函数是单位阶跃函数(Heaviside step function
)。也使用符号函数 sgn
。
单一TLU
可用于简单的线性二元分类。它计算输入的线性组合,如果结果超过阈值,它输出正类或者输出负类(就像逻辑回归分类或线性SVM
分类)。
一个具有两个输入神经元、一个偏置神经元和三个输出神经元的感知机架构:
当一层的神经元连接着前一层的每个神经元时,该层被称为全连接层,或紧密层(dense)
此外,通常再添加一个偏置特征(X0=1X_0=1X0=1):这种偏置特性通常用一种称为偏置神经元的特殊类型的神经元来表示,它总是输出 1
感知机的训练:
wi,jnextstep=wi,j+η(yj−y^j)xiwi,j:第i个输入神经元和第j个输出神经元之间的连接权重xi:是当前训练实例的第i个输入w_{i,j}^{next step}=w_{i,j}+\eta(y_j-\hat y_j)x_i \\ w_{i,j} : 第i个输入神经元和第j个输出神经元 之间的连接权重\\ x_i : 是当前训练实例的第i个输入\\ wi,jnextstep=wi,j+η(yj−y^j)xiwi,j:第i个输入神经元和第j个输出神经元之间的连接权重xi:是当前训练实例的第i个输入
Scikit-Learn
提供了一个 Perceptron
类(感知器),它实现了一个 单 TLU
网络。它可以实现大部分功能
感知器学习算法和随机梯度下降很像。事实上,sklearn
的Perceptron
类相当于使用具有以下超参数的SGDClassifier:loss="perceptron",learning_rate="constant",eta0=1
(学习率),penalty=None
(无正则化)。
与逻辑回归分类器相反,感知机不输出类概率,而是基于硬阈值进行预测。这是逻辑回归优于感知机的一点。
感知机的一些局限性可以通过堆叠多个感知机消除。由此产生的人工神经网络被称为多层感知机(MLP
)
多层感知机(MLP)与反向传播
MLP
由一个输入层、一个或多个称为隐藏层的 TLU
组成,一个 TLU
层称为输出层。靠近输入层的层,通常被称为浅层,靠近输出层的层通常被称为上层。除了输出层,每一层都有一个偏置神经元,并且全连接到上一层。
注意:信号是从输入到输出单向流动的,因此这种架构被称为前馈神经网络(FNN
)
多年来,研究人员努力寻找一种训练 MLP
的方法,但没有成功。但在 1986,David Rumelhart、Geoffrey Hinton、Ronald Williams
发表了一篇突破性的论文,提出了至今仍在使用的反向传播训练算法。
对 BP
( 反向传播) 做详细分解:
- 每次处理一个微批次(假如每个批次包含 32 个实例),用训练集多次训练
BP
,大家多称之为一个周期、纪元或轮次(epoch); - 每个微批次先进入输入层,输入层再将其发到第一个隐藏层。计算得到该层所有神经元的(微批次的每个实例的)输出。输出接着传到下一层,直到得到输出层的输出。这个过程就是前向传播:就像做预测一样,只是保存了每个中间结果,中间结果要用于反向传播;
- 然后计算输出误差(使用损失函数比较目标值和实际输出值,然后返回误差);
- 接着,计算每个输出连接对误差的贡献量。这是通过链式法则(就是对多个变量做微分的方法)实现的;
- 然后还是使用链式法则,计算最后一个隐藏层的每个连接对误差的贡献,这个过程不断向后传播,直到到达输入层。
- 最后,
BP
算法做一次梯度下降步骤,用刚刚计算的误差梯度调整所有连接权重。 - 注意:epoch的理解:每次训练都先是要设置周期 epoch 数,每个 epoch 其实做的就是三件事:向前传一次、向后传一次、然后调整参数。接着再进行下一次 epoch。
- 注意:随机初始化隐藏层的连接权重是很重要的。
为了使 BP
算法正常工作。用其他的激活函数代替阶跃函数(平坦,不可导,链式失效)。
同时,不同层之间如果还都是线性的,再深的网络等效于单层的网络,解决不了复杂问题。足够深并且有非线性激活函数的深度神经网络DNN
,在理论上可以近似于任意连续函数。
常用的激活函数有:
- sigmoid函数:σ(z)=11+exp(−z)sigmoid函数:\sigma(z)=\frac{1}{1+exp(-z)}sigmoid函数:σ(z)=1+exp(−z)1
- 双曲正切函数:tanh(z)=2σ(2z)−1双曲正切函数:tanh(z)=2 \sigma(2z)-1双曲正切函数:tanh(z)=2σ(2z)−1
- ReLU函数:ReLU(z)=max(0,z)ReLU函数: ReLU(z)=max(0,z)ReLU函数:ReLU(z)=max(0,z)
回归MLP
MLP
可以用于回归任务。如果想要预测一个单值(如房价预测),就只需要一个输出神经元,它的输出值就是预测值。
对于多变量回归(即一次预测多个值),则每一维度都要有一个神经元。如要定位一张图片的中心,就要预测 2D
坐标,因此需要两个输出神经元。要给对象加个边框,还需要两个值:对象的宽度和高度
通常,当用 MLP
做回归时,输出神经元不需要任何激活函数
训练中的损失函数一般是均方误差,但如果训练集有许多异常值,则可以使用平均绝对误差。另外,也可以使用 Huber
损失函数,它是前两者的组合。
分类 MLP
MLP
也可用于分类,对于二元分类问题,只需要一个使用 Logistic 激活的输出神经元:输出是一个 0 和 1 之间的值,作为正类的估计概率。
MLP
也可以处理多标签二元分类
如果每个实例只能属于一个类,但可能是三个或多个类中的一个(如对于数字图片的分类),则每一类都要有一个输出神经元,整个输出层要使用 softmax
激活函数。softmax
函数可以保证,每个估计概率位于 0 和 1 之间,并且各个值相加等于 1。这被称为多类分类。
用 Keras
实现 MLP
(TensorFlow
后端)
使用 Sequential API
创建图片分类器
示例代码:
import tensorflow as tf
from tensorflow import keras
## 1.导入数据集,观察分析数据
fashion_mnist = keras.datasets.fashion_mnist
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()
#拿数据集
X_train_full.shape #(60000, 28, 28)
X_test.shape #(10000, 28, 28)X_valid, X_train = X_train_full[:5000] / 255., X_train_full[5000:] / 255.
y_valid, y_train = y_train_full[:5000], y_train_full[5000:]
X_test = X_test / 255.#拆分验证集,前5000;拆分 训练集 ,后55000,并归一化数据
import collections
collections.Counter(y_train_full) #图片分成10个类别,索引号是: 0-9class_names = ["T-shirt/top", "Trouser", "Pullover", "Dress", "Coat","Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]
#每个类别的名称plt.imshow(X_train[0], cmap="binary")
plt.axis('off')
plt.show()y_train[0] # 4
class_names[y_train[0]] #Coat##2 。创建模型
model = keras.models.Sequential([keras.layers.Flatten(input_shape=[28, 28]), #输入层 28*28=784个输入keras.layers.Dense(300, activation="relu"), #隐藏层1,300个神经元全连接,relu激活函数keras.layers.Dense(100, activation="relu"), #隐藏层2,100个神经元全连接,relu激活函数keras.layers.Dense(10, activation="softmax") #输出层,10个神经元(按10个类别),softmax激活函数(分类间互斥)
])model.summary()
# 查看模型摘要,依层次,每层784*300+300个权重和偏置参数;30100个参数,1010个参数。hidden1 = model.layers[1]
weights, biases = hidden1.get_weights() #拿到第1层的权重和偏置 ,权重随机,偏置默认0?##3.编译模型
model.compile(loss="sparse_categorical_crossentropy", #损失函数,稀疏分类交叉熵。此例标签是数字而非one-hot.optimizer="sgd", #随机梯度下降metrics=["accuracy"]) #精准度评估##4. 训练模型
history = model.fit(X_train, y_train, epochs=30, #30个周期validation_data=(X_valid, y_valid))##5. 评估模型
model.evaluate(X_test, y_test)
# 313/313 [==============================] - 1s 2ms/step - loss: 0.3339 - accuracy: 0.8838##6.分片出新数据,验证效果
X_new = X_test[:3]
y_proba = model.predict(X_new)
y_proba.round(2)
#array([[0. , 0. , 0. , 0. , 0. , 0.01, 0. , 0.03, 0. , 0.96],
# [0. , 0. , 0.99, 0. , 0.01, 0. , 0. , 0. , 0. , 0. ],
# [0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]],#y_pred = model.predict_classes(X_new) # deprecated 已启用
y_pred = np.argmax(model.predict(X_new), axis=-1)
y_pred
#array([9, 2, 1]) ,如上,用分类概率最大的,9 ,2, 1plt.figure(figsize=(7.2, 2.4))
for index, image in enumerate(X_new):plt.subplot(1, 3, index + 1)plt.imshow(image, cmap="binary", interpolation="nearest")plt.axis('off')plt.title(class_names[y_test[index]], fontsize=12)
plt.subplots_adjust(wspace=0.2, hspace=0.5)plt.show()
使用 Functional API 搭建复杂模型
示例代码:
# 导入数据集
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScalerhousing = fetch_california_housing()
# 切片
X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, housing.target, random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full, random_state=42)scaler = StandardScaler() # 标准化
X_train = scaler.fit_transform(X_train)
X_valid = scaler.transform(X_valid)
X_test = scaler.transform(X_test)#function api -1
input_ = keras.layers.Input(shape=X_train.shape[1:])
# 输入层 ,8列数据,8个输入
hidden1 = keras.layers.Dense(30, activation="relu")(input_)
# 30个神经元,对应下一层 30*(8+1)个参数
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
# 30个神经元,对应下一层30*31个参数
concat = keras.layers.concatenate([input_, hidden2])
# 做合并层 30+8个输入
output = keras.layers.Dense(1)(concat)
# 合并层连接输出层,对应输出层,有:38+1个参数
model = keras.models.Model(inputs=[input_], outputs=[output])
# 建立模型model.summary()
# 查看#function api -2
input_A = keras.layers.Input(shape=[5], name="wide_input") # 特征0-4
input_B = keras.layers.Input(shape=[6], name="deep_input") # 特征2-7
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_A, hidden2]) # 合并
output = keras.layers.Dense(1, name="output")(concat) # 输出
model = keras.models.Model(inputs=[input_A, input_B], outputs=[output]) #创建模型,注意:是两个输入#编译、训练、评估预测1
model.compile(loss="mean_squared_error", optimizer=keras.optimizers.SGD(lr=1e-3)) #mse
history = model.fit(X_train, y_train, epochs=20,validation_data=(X_valid, y_valid))
mse_test = model.evaluate(X_test, y_test)
y_pred = model.predict(X_new)#编译、训练、评估预测2
model.compile(loss="mse", optimizer=keras.optimizers.SGD(lr=1e-3))X_train_A, X_train_B = X_train[:, :5], X_train[:, 2:]
X_valid_A, X_valid_B = X_valid[:, :5], X_valid[:, 2:]
X_test_A, X_test_B = X_test[:, :5], X_test[:, 2:]
X_new_A, X_new_B = X_test_A[:3], X_test_B[:3]history = model.fit((X_train_A, X_train_B), y_train, epochs=20,validation_data=((X_valid_A, X_valid_B), y_valid))
mse_test = model.evaluate((X_test_A, X_test_B), y_test)
y_pred = model.predict((X_new_A, X_new_B))
如图,接上例,还可以处理多个输出,示例代码:
input_A = keras.layers.Input(shape=[5], name="wide_input")
input_B = keras.layers.Input(shape=[6], name="deep_input")
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
output = keras.layers.Dense(1, name="main_output")(concat)
aux_output = keras.layers.Dense(1, name="aux_output")(hidden2)model = keras.models.Model(inputs=[input_A, input_B],outputs=[output, aux_output])model.compile(loss=["mse", "mse"], loss_weights=[0.9, 0.1], optimizer=keras.optimizers.SGD(lr=1e-3)) #损失函数和权重是两套history = model.fit([X_train_A, X_train_B], [y_train, y_train], epochs=20,validation_data=([X_valid_A, X_valid_B], [y_valid, y_valid]))total_loss, main_loss, aux_loss = model.evaluate([X_test_A, X_test_B], [y_test, y_test])
y_pred_main, y_pred_aux = model.predict([X_new_A, X_new_B])
保存和恢复模型
model = keras.models.Sequential([keras.layers.Dense(30, activation="relu", input_shape=[8]),keras.layers.Dense(30, activation="relu"),keras.layers.Dense(1)
]) model.compile(loss="mse", optimizer=keras.optimizers.SGD(lr=1e-3))
history = model.fit(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
mse_test = model.evaluate(X_test, y_test)model.save("my_keras_model.h5")model = keras.models.load_model("my_keras_model.h5")model.predict(X_new)model.save_weights("my_keras_weights.ckpt")model.load_weights("my_keras_weights.ckpt")
使用调回
fit()方法接受参数callbacks,可以让用户指明一个 Keras
列表,让 Keras
在训练开始和结束、每个周期开始和结束、甚至是每个批次的前后调用。例如,ModelCheckpoint
可以在每个时间间隔保存检查点,默认是每个周期结束之后:
如果训练时使用了验证集,可以在创建检查点时设定save_best_only=True,只有当模型在验证集上取得最优值时才保存模型。这么做可以不必担心训练时间过长和训练集过拟合:只需加载训练好的模型,就能保证是在验证集上表现最好的模型。
使用 TensorBoard 进行可视化
You can then open your web browser to localhost:6006 and use TensorBoard.
《蜥蜴书》_讲义及源码解读_10相关推荐
- 《蜥蜴书》_讲义及源码解读_09
无监督学习 文章目录 无监督学习 聚类Clustering 聚类的应用领域: K-Means算法 示例代码:使用`make_blobs`生成数据 示例代码:训练拟合和预测 硬聚类和软聚类: `K-Me ...
- python组件的react实现_【React源码解读】- 组件的实现
前言 react使用也有一段时间了,大家对这个框架褒奖有加,但是它究竟好在哪里呢? 让我们结合它的源码,探究一二!(当前源码为react16,读者要对react有一定的了解) 回到最初 根据react ...
- GeoTools源码解读 - XML处理 - Encoder
GeoTools中的XML处理 - 如何将Object转换为XML文档. 文章目录 1. 前言 2. 概述 3. 用例准备 4. 实现原理 4.1 内部类`Encoder.EncodingEntry` ...
- 【赠书福利】掘金爆火小册同名《Spring Boot源码解读与原理剖析》正式出书了!...
关注我们丨文末赠书 承载着作者的厚望,掘金爆火小册同名读物<Spring Boot源码解读与原理剖析>正式出书! 本书前身是掘金社区销量TOP的小册--<Spring Boot源码解 ...
- aqs java 简书,Java AQS源码解读
1.先聊点别的 说实话,关于AQS的设计理念.实现.使用,我有打算写过一篇技术文章,但是在写完初稿后,发现掌握的还是模模糊糊的,模棱两可. 痛定思痛,脚踏实地重新再来一遍.这次以 Java 8源码为基 ...
- hystrix 源码 线程池隔离_“池”的思想:从java线程池到数据库连接池的源码解读(1)...
一. java线程池 带着问题: 线程是什么时候被创建的? 线程会一直循环取任务任务吗?怎么做的? 线程取不到任务会怎么样? 线程会被Runnable和Callable的异常干掉吗? 线程怎么干掉自己 ...
- mysql8.0源代码解析_源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统
原标题:源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统 作者介绍 张永翔,现任网易云RDS开发,持续关注MySQL及数据库运维领域,擅长MySQL运维,知乎ID:雁南归. MySQL ...
- Bert系列(二)——源码解读之模型主体
本篇文章主要是解读模型主体代码modeling.py.在阅读这篇文章之前希望读者们对bert的相关理论有一定的了解,尤其是transformer的结构原理,网上的资料很多,本文内容对原理部分就不做过多 ...
- Bert系列(三)——源码解读之Pre-train
https://www.jianshu.com/p/22e462f01d8c pre-train是迁移学习的基础,虽然Google已经发布了各种预训练好的模型,而且因为资源消耗巨大,自己再预训练也不现 ...
最新文章
- python话雷达图-python使用matplotlib绘制雷达图
- VC6.0连接数据库,并把大量数据从ACCess转移到SQL sever2008 的问题(亲测可用)
- python语句-浅谈 Python 的 with 语句
- C#——《C#语言程序设计》实验报告——泛型与集合——运算符重载
- ps -ef和ps aux
- c语言中输出9个空格,新人提问:如何将输出时每行最后一个空格删除
- 在centos7上使用Docker安装oracle 11g
- 输入学号姓名输出学号姓名c语言,急啊!!!求救了 C语言编一个链表,输出姓名和学号就好...
- 让51单片机八段数码管亮起来(静态显示和动态显示、共阴极和共阳极、位码和段码)
- Spring之IOC快速入门(一)
- C#基础回顾:正则表达式
- 怎样读取html控件(如文本框)的值
- python缩进格式错误修改_Python,意外的缩进错误解析,Pythonunexpectedindent,解决,方法...
- mysql innodb数据库引擎_mysql的innodb数据库引擎详解
- Windows XP 禁用屏幕保护功能
- 电子商务世界历程及国内历程
- 服务器虚拟化的重要性,服务器虚拟化:虚拟机迁移的重要性
- 智能建筑现状及发展趋势,建筑智能化的发展趋势
- sqlserver恢复已经删除的表记录
- java如何改变图片大小_如何在Java中调整图片大小?
热门文章
- ReentrantReadWriteLock原理与使用
- 第三方应用微信退款功能
- html用接口实现手机验证码发送,编写程序软件怎样才能实现向手机号码发送验证码?需要调用哪些接口?...
- 电动车控制器电路原理图讲解分析
- 基于Adobe After Effects从去除视频水印到“跟踪运动”替换动态元素(文字)
- 产品定位最关健的四要素
- 内网渗透常用命令大全适合初学者
- SnowFlake(雪花算法)
- 基于有源钳位三电平的有源电力滤波器
- SQL*Plus中plustrce.sql(SP2-0613、SP2-0611)和(SP2-0618、SP2-0611)