Spaces:
Paused
Paused
# -*- coding:utf-8 -*- | |
# VGG模型代码 | |
import numpy as np | |
import paddle | |
# from paddle.nn import Conv2D, MaxPool2D, BatchNorm, Linear | |
from paddle.nn import Conv2D, MaxPool2D, BatchNorm2D, Linear | |
# 定义vgg网络 | |
class VGG(paddle.nn.Layer): | |
def __init__(self, num_class): | |
super(VGG, self).__init__() | |
in_channels = [3, 64, 128, 256, 512, 512] | |
# 定义第一个卷积块,包含两个卷积 输入通道数是图片通道数即3 输出通道数即out_channels=in_channels[1]=64 | |
self.conv1_1 = Conv2D(in_channels=in_channels[0], out_channels=in_channels[1], kernel_size=3, padding=1, | |
stride=1) | |
self.conv1_2 = Conv2D(in_channels=in_channels[1], out_channels=in_channels[1], kernel_size=3, padding=1, | |
stride=1) | |
# 定义第二个卷积块,包含两个卷积 输入通道数是上一个卷积块的输出通道数即64 输出通道数即out_channels=in_channels[2]=128 | |
self.conv2_1 = Conv2D(in_channels=in_channels[1], out_channels=in_channels[2], kernel_size=3, padding=1, | |
stride=1) | |
self.conv2_2 = Conv2D(in_channels=in_channels[2], out_channels=in_channels[2], kernel_size=3, padding=1, | |
stride=1) | |
# 定义第三个卷积块,包含三个卷积 输入通道数是上一个卷积块的输出通道数即128 输出通道数即out_channels=in_channels[3]=256 | |
self.conv3_1 = Conv2D(in_channels=in_channels[2], out_channels=in_channels[3], kernel_size=3, padding=1, | |
stride=1) | |
self.conv3_2 = Conv2D(in_channels=in_channels[3], out_channels=in_channels[3], kernel_size=3, padding=1, | |
stride=1) | |
self.conv3_3 = Conv2D(in_channels=in_channels[3], out_channels=in_channels[3], kernel_size=3, padding=1, | |
stride=1) | |
# 定义第四个卷积块,包含三个卷积 输入通道数是上一个卷积块的输出通道数即256 输出通道数即out_channels=in_channels[4]=512 | |
self.conv4_1 = Conv2D(in_channels=in_channels[3], out_channels=in_channels[4], kernel_size=3, padding=1, | |
stride=1) | |
self.conv4_2 = Conv2D(in_channels=in_channels[4], out_channels=in_channels[4], kernel_size=3, padding=1, | |
stride=1) | |
self.conv4_3 = Conv2D(in_channels=in_channels[4], out_channels=in_channels[4], kernel_size=3, padding=1, | |
stride=1) | |
# 定义第五个卷积块,包含三个卷积 输入通道数是上一个卷积块的输出通道数即512 输出通道数即out_channels=in_channels[5]=512 | |
self.conv5_1 = Conv2D(in_channels=in_channels[4], out_channels=in_channels[5], kernel_size=3, padding=1, | |
stride=1) | |
self.conv5_2 = Conv2D(in_channels=in_channels[5], out_channels=in_channels[5], kernel_size=3, padding=1, | |
stride=1) | |
self.conv5_3 = Conv2D(in_channels=in_channels[5], out_channels=in_channels[5], kernel_size=3, padding=1, | |
stride=1) | |
# VGG网络的设计严格使用3*3的卷积层和池化层来提取特征,并在网络的最后面使用三层全连接层,将最后一层全连接层的输出作为分类的预测。 | |
# 使用Sequential 将全连接层和relu组成一个线性结构(fc + relu) | |
# 当输入为224x224时,经过五个卷积块和池化层后,特征维度变为[512x7x7] | |
self.fc1 = paddle.nn.Sequential(paddle.nn.Linear(512 * 7 * 7, 4096), paddle.nn.ReLU()) | |
self.drop1_ratio = 0.5 | |
self.dropout1 = paddle.nn.Dropout(self.drop1_ratio, mode='upscale_in_train') | |
# 使用Sequential 将全连接层和relu组成一个线性结构(fc + relu) | |
self.fc2 = paddle.nn.Sequential(paddle.nn.Linear(4096, 4096), paddle.nn.ReLU()) | |
self.drop2_ratio = 0.5 | |
self.dropout2 = paddle.nn.Dropout(self.drop2_ratio, mode='upscale_in_train') | |
# 全连接层的输出 | |
# paddle.nn.Linear(in_features, out_features, weight_attr=None, bias_attr=None, name=None) | |
# out_features 由输出标签的个数决定 本案例识别的7种表情,对应了3种标签。 因此 out_features = 3 | |
self.fc3 = paddle.nn.Linear(4096, num_class) | |
self.relu = paddle.nn.ReLU() | |
self.pool = MaxPool2D(stride=2, kernel_size=2) | |
def forward(self, x): | |
# 激活函数用relu | |
x = self.relu(self.conv1_1(x)) | |
x = self.relu(self.conv1_2(x)) | |
x = self.pool(x) | |
x = self.relu(self.conv2_1(x)) | |
x = self.relu(self.conv2_2(x)) | |
x = self.pool(x) | |
x = self.relu(self.conv3_1(x)) | |
x = self.relu(self.conv3_2(x)) | |
x = self.relu(self.conv3_3(x)) | |
x = self.pool(x) | |
x = self.relu(self.conv4_1(x)) | |
x = self.relu(self.conv4_2(x)) | |
x = self.relu(self.conv4_3(x)) | |
x = self.pool(x) | |
x = self.relu(self.conv5_1(x)) | |
x = self.relu(self.conv5_2(x)) | |
x = self.relu(self.conv5_3(x)) | |
x = self.pool(x) | |
x = paddle.flatten(x, 1, -1) | |
# 添加dropout抑制过拟合 | |
x = self.dropout1(self.relu(self.fc1(x))) | |
x = self.dropout2(self.relu(self.fc2(x))) | |
x = self.fc3(x) | |
return x |