本项目是基于PaddlePaddle深度学习框架来开发自动巡线模型框架,开发思路是通过手柄驱动小车巡线的来读取手柄偏移值配合图像来生成数据集内容,借用AlexNet神经网络模型
import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Conv2D, Linear, Pool2D
import cv2
import json
import numpy as np
import os
import re
import random
datafile = json.load(open("result.json")) # file是一个字典类型
def transform_img(img):
# 将图片归一化保证图片最后为-1到1的数组
img = cv2.resize(img, (224, 224))
img = np.transpose(img, (2, 0, 1))
img = img.astype("float32")
img = img / 255
img = img * 2.0 - 1.0
return img
def data_loader(datadir, batch_size = 10, mode = "train"):
filenames = os.listdir(datadir)
def reader():
random.shuffle(filenames) # 随机打乱训练集
batch_imgs = []
batch_labels = []
for name in filenames:
# 读取数据集
filepath = os.path.join(datadir, name)
img = cv2.imread(filepath)
img = transform_img(img)
index = re.findall(r"\d+", name)
label = datafile[index[0]]
batch_imgs.append(img)
batch_labels.append(label)
# 打包成mini-batch
if len(batch_imgs) == batch_size:
# 设置mini-batch
imgs_array = np.array(batch_imgs).astype("float32")
labels_array = np.array(batch_labels).astype("float32").reshape(-1, 1)
yield imgs_array, labels_array # 设置迭代器
batch_imgs = []
batch_labels = []
if len(batch_imgs) > 0:
# 剩余样本数量不足一个batch_size的数据,一起打包成一个mini_batch
imgs_array = np.array(batch_imgs).astype("float32")
labels_array = np.array(batch_labels).astype("float32").reshape(-1, 1)
yield imgs_array, labels_array
return reader
data_dir = "train"
train_loader = data_loader(data_dir, batch_size = 10, mode = "train")
data_reader = train_loader()
data = next(data_reader) # 返回迭代器下一个项目
def train(model):
with fluid.dygraph.guard():
print("start training......")
model.train()
epoch_num = 5
opt = fluid.optimizer.Momentum(learning_rate = 0.001, momentum = 0.9, parameter_list = model.parameters())
train_loader = data_loader(data_dir, batch_size = 10, mode = "train")
for epoch in range(epoch_num):
for batch_id, data in enumerate(train_loader()):
x_data, y_data = data
img = fluid.dygraph.to_variable(x_data)
label = fluid.dygraph.to_variable(y_data)
# 模型前向运算
logits = model(img)
# loss运算
# 使用mean均方差函数求loss
loss = fluid.layers.mse_loss(logits, label)
avg_loss = fluid.layers.mean(loss)
if batch_id % 10 == 0:
print("epoch:{},batch_id:{},loss is {}".format(epoch, batch_id, avg_loss.numpy()))
# 反向传播,更新权重,清除梯度
avg_loss.backward()
opt.minimize(avg_loss)
model.clear_gradients()
model.eval()
model.train()
# 保存权重值
fluid.save_dygraph(model.state_dict(), "CNN")
fluid.save_dygraph(opt.state_dict(), "CNN")
def evaluation(model, params_file_path):
with fluid.dygraph.guard():
print("start evaluation.......")
model_state_dict, _ = fluid.load_dygraph(params_file_path)
model.load_dict(model_state_dict)
model.eval()
eval_loader = data_loader(data_dir, batch_size = 10, mode = "eval")
acc_set = []
avg_loss_set = []
for batch_id, data in enumerate(eval_loader()):
x_data, y_data = data
img = fluid.dygraph.to_variable(x_data)
label = fluid.dygraph.to_variable(y_data)
y_data = y_data.astype(np.float32)
label_64 = fluid.dygraph.to_variable(y_data)
# 计算预测和精度
prediction, acc = model(img, label)
# 计算损失函数值
loss = fluid.layers.mse_loss(input = prediction, label = label) # 这里改过
avg_loss = fluid.layers.mean(loss)
acc_set.append(float(acc.numpy()))
avg_loss_set.append(float(avg_loss.numpy()))
# 求平均精度
acc_val_mean = np.array(acc_set).mean()
avg_loss_val_mean = np.array(avg_loss_set).mean()
print("loss = {},acc = {}".format(avg_loss_val_mean, acc_val_mean))
class AlexNet(fluid.dygraph.Layer):
def __init__(self, num_classes = 1):
super(AlexNet, self).__init__()
self.conv1 = Conv2D(num_channels = 3, num_filters = 96, filter_size = 11, stride = 4, padding = 5, act = "relu")
self.pool1 = Pool2D(pool_size = 2, pool_stride = 2, pool_type = "max")
self.conv2 = Conv2D(num_channels = 96, num_filters = 256, filter_size = 5, stride = 1, padding = 2, act = "relu")
self.pool2 = Pool2D(pool_size = 2, pool_stride = 2, pool_type = "max")
self.conv3 = Conv2D(num_channels = 256, num_filters = 384, filter_size = 3, stride = 1, padding = 1, act = "relu")
self.conv4 = Conv2D(num_channels = 384, num_filters = 384, filter_size = 3, stride = 1, padding = 1, act = "relu")
self.conv5 = Conv2D(num_channels = 384, num_filters = 256, filter_size = 3, stride = 1, padding = 1, act = "relu")
self.pool5 = Pool2D(pool_size = 2, pool_stride = 2, pool_type = "max")
self.fc1 = Linear(input_dim = 12544, output_dim = 4096, act = "relu")
self.drop_ratio1 = 0.5
self.fc2 = Linear(input_dim = 4096, output_dim = 4096, act = "relu")
self.drop_ratio2 = 0.5
self.fc3 = Linear(input_dim = 4096, output_dim = num_classes)
def forward(self, x):
x = self.conv1(x)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.conv3(x)
x = self.conv4(x)
x = self.conv5(x)
x = self.pool5(x)
x = fluid.layers.reshape(x, [x.shape[0], -1])
x = self.fc1(x)
x = fluid.layers.dropout(x, self.drop_ratio1)
x = self.fc2(x)
x = fluid.layers.dropout(x, self.drop_ratio2)
x = self.fc3(x)
predict = fluid.layers.tanh(x)
return predict
if __name__ == "__main__":
with fluid.dygraph.guard():
model = AlexNet()
train(model)