设计一个基于深度学习的生活垃圾分类机器人软件系统,针对现实社会中产生的垃圾照片进行自动识别分类,对不同类别的垃圾,干垃圾,湿垃圾,可回收垃圾,有害垃圾等进行分类统计处理,减轻人工针对垃圾分类的工作量,提高垃圾分类的效率。
原文地址
本基于深度学习的生活垃圾分类机器人软件,系统基础建设功能是垃圾的收集分类,因此需要针对垃圾数据的同图片采集的方式通过深度学习训练垃圾识别模型,进而实现从不同垃圾图片样本中识别垃圾种类。因此在针对垃圾数据识别训练之前,需要准备训练使用的样本数据图片集合,此部分采用网络爬虫的技术手段收集互联网中存在的垃圾图片样本,进行归类整理。垃圾数据图片收集的爬取过程逻辑,具体如图所示。
本次毕设系统在设计中,主要采用ResNext101_32x16d_WSL网络作为基本的网络结构进行迁移学习,将CBAM注意力机制模块添加在首层卷积层,来增强图像特征表征能力,关注图像的重要特征抑制不必要的特征,固定除全连接层之外的其他层的权重。为降低过拟合,在模型全连接层添加了Dropout层,损失函数采用交叉熵损失函数,优化函数对比了SGD和Adam,Adam在起始收敛速度快,但最终SGD精度高,所以采用了SGD。最终模型结构如图所示。
核心实现源码
import numpy as np
import scipy.io
import matplotlib.pyplot as plt
class Pegasos:
def __init__(self, train_path, test_path, C, T, loss):
self.__dataprocess(train_path, test_path)
self.n = len(self.train_x)
self.C = C
self.T = T
self.lam = 1/(self.n*self.C)
self.loss = loss
self.W = np.random.randn(1899, 1)
self.b = np.random.randn(1, 1)
self.choose = np.random.choice(self.n, self.T, replace = True)
self.__Pegasos()
def __dataprocess(self, train_path, test_path):
''' 数据处理函数'''
train_set = scipy.io.loadmat(train_path)
test_set = scipy.io.loadmat(test_path)
self.train_x = train_set['X']
self.test_x = test_set['Xtest']
self.train_y = train_set['y'].astype(np.int16) * 2 - 1
self.test_y = test_set['ytest'].astype(np.int16) * 2 - 1
def __Pegasos(self):
''' 通过 Pegasos 算法训练模型, st为 y * (wx + b)'''
cost = []
for t in range(1, self.T + 1):
eta = 1 / (self.lam * t)
st = self.train_y[self.choose[t-1]][0] * self.classifier(self.train_x[self.choose[t-1]])
self.W, self.b = self.loss.gradDes(self.W, self.b,
np.swapaxes([self.train_x[self.choose[t-1]]], 0, 1),
self.train_y[self.choose[t-1]][0], st,
self.lam, eta)
cost.append(self.loss.loss(self.W, self.lam, st))
self.__plot(cost)
def classifier(self, x):
'''分类器, 当前 W, b 下模型计算结果'''
return np.matmul(x, self.W) + self.b
def classify(self):
'''
分类: 使用训练后的模型对训练集、测试集分类, 并将正确分类的数量存储在数组 num 中
使用数组? 因为懒得为两个数据集合起两个名字了
'''
num = [0, 0]
for i in range(len(self.train_y)):
num[0] += 1 if self.classifier(self.train_x[i]) * self.train_y[i][0] >= 1 else 0
for i in range(len(self.test_y)):
num[1] += 1 if self.classifier(self.test_x[i]) * self.test_y[i][0] >= 1 else 0
self.__print(num)
def __print(self, num):
''' 打印模型在训练集和测试集上的测试结果'''
print('支持向量机')
print('C = ', self.C)
print('T = ', self.T)
print('训练集acc = {}, {}/{}'.format(num[0]/len(self.train_y), num[0], len(self.train_y)))
print('测试集acc = {}, {}/{}'.format(num[1]/len(self.test_y), num[1], len(self.test_y)))
def __plot(self, cost):
''' 绘制目标函数梯度下降的图像'''
t = np.arange(self.T)
plt.plot(t, cost, 'r')
plt.title("C = {}, T = {}, loss: {}".format(self.C, self.T, self.loss.__name__))
plt.legend()
plt.savefig('../output/{}/{}_{}.png'.format(self.loss.__name__, self.C, self.T))
class hinge:
@staticmethod
def gradDes(W, b, x, y, st, lam, eta):
if st < 1 :
W -= eta * (lam * W - y * x)
b += eta * y
else:
W -= eta * lam * W
return W, b
@staticmethod
def loss(W, lam, st):
return np.linalg.det(lam / 2 * np.matmul(np.swapaxes(W,0,1), W) + np.max([0, 1-st]))
class exponential:
@staticmethod
def gradDes(W, b, x, y, st, lam, eta):
if st < -8: st = -8
exp = np.exp(-st)
W -= eta * (lam * W - y * x * exp)
b += eta * y * exp
return W, b
@staticmethod
def loss(W, lam, st):
return np.linalg.det(lam / 2 * np.matmul(np.swapaxes(W,0,1), W) + np.exp(-st))
class logistic:
@staticmethod
def gradDes(W, b, x, y, st, lam, eta):
exp = np.exp(-st)
W -= eta * (lam * W - y * x * exp / (1 + exp))
b += eta * y * exp / (1 + exp)
return W, b
@staticmethod
def loss(W, lam, st):
return np.linalg.det(lam / 2 * np.matmul(np.swapaxes(W,0,1), W) + np.log(1 + np.exp(-st)))