前言: 第二节课,老师讲解了4个简单神经网络,循序渐进,思路清晰。不过这个是基于我本身就对深度学习有一定概念认知的基础上,如果是第一次听可能一头雾水
(直播时就有人吵,同为小白的我都感到丢脸)。第二次看详细的paddle网络代码讲解,第一次是七日图像分割。现在已经对paddle框架有了认知了,之后的进度应该会顺利一点。
- 我忘记了很多神经网络的细节,在写第二次作业时才发现这个问题。然后我发现以下的笔记很多都在胡扯,只有最后的总结和复制老师的程序能参考一下。在此提前说一下。
———————————————
课程文档:
https://aistudio.baidu.com/aistudio/education/preview/1106964
项目合集
https://aistudio.baidu.com/aistudio/projectdetail/1354419
基于PaddlePaddle2.0-构建线性回归模型
https://aistudio.baidu.com/aistudio/projectdetail/1322247
【目录】【中文】【deplearning.ai】【吴恩达课后作业目录】
https://blog.csdn.net/u013733326/article/details/79827273
其他学习者的笔记:神经网络(深度学习)从入门到精通(放弃)
https://blog.csdn.net/u014162133/article/details/81181194
import numpy
num_inputs=2 # 定义输入参数数量
num_examples=500 # 定义训练次数
true_w=[1.2,2.5] # 定义需要生成数据的参数,也是模型训练的最终目标w
true_b=6.8 # 定义需要生成数据的参数,也是模型训练的最终目标b
# 随机生成x
features = numpy.random.normal(0,1,(num_examples, num_inputs)).astype('float32')
# 利用随机生成的x,生成y
labels = features[:,0]*true_w[0]+features[:,1]*true_w[1]+true_b
# 增加不确定变量叠加在y上,很小的一个偏置(如果不增加,几个式子就可以解方程得出答案)
labels = labels + numpy.random.normal(0,0.001,labels.shape[0])
# 转换数组的数据类型
labels = labels.astype('float32')
#注意:需要在最后增加一个维度 嗯嗯嗯,这个操作大概是为paddle框架用的。
labels = numpy.expand_dims(labels,axis=-1)
Tensor
数据类型,至关重要的基础知识。“Tensor是类似于 Numpy array 的概念。”paddle.nn.Linear()
等函数的运用,这是飞桨框架的核心特点 —— 一句定义一层。飞桨开发指南-一文带你了解飞桨静态图运行机制
https://aistudio.baidu.com/aistudio/projectdetail/462062?qq-pf-to=pcqq.group
import paddle
# 将普通的Numpy转换为Paddle框架能用的Tensor类型
train_data=paddle.to_tensor(features)
# 上一行是转换输入数据,下一行是转换输出数据
y_true=paddle.to_tensor(labels)
# 定义一层网络,输入2,输出1。
model=paddle.nn.Linear(in_features=2, out_features=1)
# 实现随机梯度下降算法的优化器
sgd_optimizer=paddle.optimizer.SGD(learning_rate=0.001, parameters=model.parameters())
# 计算预测值和目标值的均方差误差。
mse_loss=paddle.nn.MSELoss()
for i in range(5000):
# 记住这种函数操作,把 输入 丢进 模型 中就可以
y_predict = model(train_data)
# 返回的值就是出,输出再和准确值计算差值
loss=mse_loss(y_predict, y_true)
# 然后“问号?”三连,
loss.backward()
sgd_optimizer.step()
sgd_optimizer.clear_grad()
# 就成功了……
print(model.weight.numpy())
[[1.2000061] [2.5001166]]
print(model.bias.numpy())
[6.799932]
print(loss.numpy())
[1.09125e-06]
loss
是损失函数的值,acc
是准确率的意思。基于PaddlePaddle2.0-构建SoftMax分类器
https://aistudio.baidu.com/aistudio/projectdetail/1323298
SoftMax分类器是根据输入特征来对离散型输出概率做出预测的模型,适用于多分类预测问题。 我们以手写数字分类为例构建一个分类器,根据手写数字的光学识别图片来预测这张图片所包含的数字。
小白都能看懂的softmax详解
https://blog.csdn.net/bitcarmanlee/article/details/82320853
信息论创始人Shannon在“通讯的数学理论”一文中指出“信息是用来消除随机不确定性的东西”。信息量衡量的是某个具体事件发生所带来的信息,信息量大小就是这个信息消除不确定性的程度。
设某个信息发生的概率为P(x),其信息量表示为:
信息熵是所有可能发生事件所带来的信息量的期望。信息熵越大,代表事物越具不确定性。设X是一个离散型随机变量,类别个数为q,信息熵表示为:
经典损失函数:交叉熵(附tensorflow)
https://blog.csdn.net/weixin_37567451/article/details/80895309
手写数字分类数据集来源MNIST数据集,该数据集可以公开免费获取。该数据集中的训练集样本数量为60000个,测试集样本数量为10000个。每个样本均是由28×28像素组成的矩阵,每个像素点的值是标量,取值范围在0至255之间。我们使用
paddle.vision.datasets.MNIST()
方法来下载和加载MNIST数据集。
import paddle
# 加载数据
train_dataset=paddle.vision.datasets.MNIST(mode="train", backend="cv2") #训练数据集
test_dataset=paddle.vision.datasets.MNIST(mode="test", backend="cv2") #测试数据集
# 设定模型,记住“paddle.nn.Sequential”这个方法,可以打包复数层网络。
linear=paddle.nn.Sequential(
paddle.nn.Flatten(),#将[1,28,28]形状的图片数据改变形状为[1,784]
paddle.nn.Linear(784,10)
)
# 利用paddlepaddle2的高阶功能,可以大幅减少训练和测试的代码量
# 把模型丢入Model
model=paddle.Model(linear)
# 下面是高阶API的用法,提前了解一下。其实就是打包了几个操作,更加方便了。
model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(), #交叉熵损失函数。线性模型+该损失函数,即softmax分类器。
paddle.metric.Accuracy(topk=(1,2)))
model.fit(train_dataset, epochs=2, batch_size=64, verbose=1)
model.evaluate(test_dataset,batch_size=64,verbose=1)
基于PaddlePaddle2.0-构建多层感知机模型
https://aistudio.baidu.com/aistudio/projectdetail/1323886
线性回归模型和SoftMax分类器都属于单层全连接神经网络,下面介绍一种具有多层结构的全连接神经网络——多层感知机。多层感知机是一种至少具有1个隐藏层的全连接神经网络,每个隐藏层输出需要经过激活函数转换。
如果是多分类问题,可以把经过激励函数转化后的值进行SoftMax
运算,输出得到样本在各类别上的概率。
这个介绍多层神经网络,也就是含隐藏层的操作。其他东西都一样,直接上代码。
大部分都一样,不过有点需要特别说明。多层网络就开始使用:定义一个模型类,初始化内定义各层网络的配置;然后其中的方法“forward()
”就是用设定的各层网络,前后搭配组合在一起,形成模型。
还有一点要注意,线性网络中,每次隐藏层输出都要接一个激活层。不要忘记了
import paddle
import paddle.nn.functional as F
from paddle.vision.transforms import ToTensor
#导入数据
train_dataset=paddle.vision.datasets.MNIST(mode="train", transform=ToTensor())
val_dataset=paddle.vision.datasets.MNIST(mode="test", transform=ToTensor())
#定义模型
class MLPModel(paddle.nn.Layer):
def __init__(self):
super(MLPModel, self).__init__()
self.flatten=paddle.nn.Flatten()
self.hidden=paddle.nn.Linear(in_features=784,out_features=128)
self.output=paddle.nn.Linear(in_features=128,out_features=10)
# 注意,多层网络就开始引入forward函数概念了。
def forward(self, x):
x=self.flatten(x)
x=self.hidden(x) #经过隐藏层
x=F.relu(x) #经过激活层,先经过激活函数再到输出10分类
x=self.output(x)
return x
model=paddle.Model(MLPModel())
# 利用paddlepaddle2的高阶功能,可以大幅减少训练和测试的代码量
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy())
model.fit(train_dataset,
epochs=5,
batch_size=64,
verbose=1)
model.evaluate(val_dataset,verbose=1)
基于PaddlePaddle2.0-构建卷积网络模型LeNet-5
https://aistudio.baidu.com/aistudio/projectdetail/1329509
LeNet-5
是卷积神经网络模型的早期代表,它由LeCun在1998年提出。该模型采用顺序结构,主要包括7层(2个卷积层、2个池化层和3个全连接层),卷积层和池化层交替排列。
conv
+池化pool
+线性+……叠加循环之类的。pool
操作也可以理解为和下采样一个意思,再大白话一点就是理解成缩小图片,放大图片就是上采样。import paddle
import paddle.nn.functional as F
from paddle.vision.transforms import Compose, Normalize
transform = Compose([Normalize(mean=[127.5],
std=[127.5],
data_format='CHW')])
#导入MNIST数据
train_dataset=paddle.vision.datasets.MNIST(mode="train", transform=transform)
val_dataset=paddle.vision.datasets.MNIST(mode="test", transform=transform)
#定义模型
class LeNetModel(paddle.nn.Layer):
def __init__(self):
super(LeNetModel, self).__init__()
# 创建卷积和池化层块,每个卷积层后面接着2x2的池化层
#卷积层L1
self.conv1 = paddle.nn.Conv2D(in_channels=1,
out_channels=6,
kernel_size=5,
stride=1)
#池化层L2
self.pool1 = paddle.nn.MaxPool2D(kernel_size=2,
stride=2)
#卷积层L3
self.conv2 = paddle.nn.Conv2D(in_channels=6,
out_channels=16,
kernel_size=5,
stride=1)
#池化层L4
self.pool2 = paddle.nn.MaxPool2D(kernel_size=2,
stride=2)
#线性层L5
self.fc1=paddle.nn.Linear(256,120)
#线性层L6
self.fc2=paddle.nn.Linear(120,84)
#线性层L7
self.fc3=paddle.nn.Linear(84,10)
#正向传播过程
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pool1(x)
x = F.relu(x)
x = self.conv2(x)
x = self.pool2(x)
x = paddle.flatten(x, start_axis=1,stop_axis=-1)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
out = self.fc3(x)
return out
model=paddle.Model(LeNetModel())
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy())
model.fit(train_dataset,
epochs=5,
batch_size=64,
verbose=1)
model.evaluate(val_dataset,verbose=1)
CIFAR10
数据集的特点是,比手写数据集分类更多。LeNet-5
模型,在处理少分类少数据时才有高准确度。当分类数、图像通道数(彩色图片三通道)时精确度就很低。具体解决方法放到下一课再细讲。以下的代码判断就是定义一个简单的多层感知器,一共有三层,两个大小为100的隐层和一个大小为10的输出层,因为MNIST数据集是手写0到9的灰度图像,类别有10个,所以最后的输出大小是10。最后输出层的激活函数是
Softmax
,所以最后的输出层相当于一个分类器。加上一个输入层的话,多层感知器的结构是:输入层–>>隐层–>>隐层–>>输出层。
# 基于PaddlePaddle2.0-构建卷积网络模型LeNet-5 的节选
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.relu(x)
out = self.fc3(x)
return out
# 基于PaddlePaddle2.0-构建多层感知机模型 的节选
x=self.flatten(x)
x=self.hidden(x) #经过隐藏层
x=F.relu(x) #经过激活层
x=self.output(x)
return x
# 基于PaddlePaddle2.0-构建SoftMax分类器 的节选
linear=paddle.nn.Sequential(
paddle.nn.Flatten(),#将[1,28,28]形状的图片数据改变形状为[1,784]
paddle.nn.Linear(784,10)# 线性模型+交叉熵损失函数,即softmax分类器。
)
paddle.nn.Linear
的返回值就含激活层操作了,现在发现好像不是。def forward(self, x):
#请在这里补全传播过程的代码
x = self.x_input(x) # 把图像拍成一维
x = self.LH_1(x) # 输入784个x,计算输出100个y
x = F.relu(x) # 输入100个y,计算100个y'
y = self.LH_2(x) # 再把100个y'当x输入,计算输出新的10个y
# y = F.relu(y) # 根据作业图片要求,事实证明不用,用了整个模型就崩掉了……
return y
SoftMax分类器
、SoftMax激活函数
的用以,一开始我居然跳过了这个知识点,现在上面的笔记已经补充了。助教说:paddle.nn.CrossEntropyLoss()中是把交叉熵损失函数和softmax一起合并在一起了,所以不要再加softmax了。你最后一层可以用relu也可以用softmax,都可以,就是训练效果的差距。
MNIST手写数字
数据集来说,我最后加和不加激活函数(softmax
或Relu
),准确率都很高,可能是数据集太简单的缘故。但是,预测结果输出却有很明显的差别,只有加了softmax
后输出结果才在0到1之间的概率,而且结果明显。softmax
。这也说明了为什么我在老师的项目例子里没有看到softmax
激活函数,因为包含在了损失函数中。print(result[0][0])
# [[ -2.661826 -3.217544 1.4394473 3.3448048 -11.59877
# -4.011869 -12.629112 10.715195 0.16913329 0.5076793 ]] # 没加softmax的线性
# [[5.6143895e-10 1.9332323e-18 1.1747437e-09 1.0818614e-09 4.8145010e-15
# 3.0116232e-09 1.4993277e-17 1.0000000e+00 1.2124682e-10 4.7770667e-09]] # 加softmax的线性
# [[-2.0730288 3.2187026 4.494609 0.716204 1.0953971 -3.124497
# -9.232485 17.074171 -1.4758562 2.4306192]] # 没加softmax的卷积
# [[9.1836060e-20 1.5012904e-25 8.1553386e-19 4.0469723e-21 1.6038109e-28
# 1.8038185e-28 1.6038109e-28 1.0000000e+00 6.5071873e-27 6.9125941e-24]] # 加softmax的卷积
# [[ 0. 0. 0. 3.1087685 0. 0.
# 0. 10.235452 0. 0.3576991]] # 加relu的线性