今天是12月1日,早上趁着跑数据的空隙来补一下上周落下的博客。
由于做实验需要用到深度学习来识别信号分类,因此我就从图片的角度来对混合信号进行识别分类。由于之前师兄有基础,我就拿师兄搭建好的mobilenet v3 轻量级网络来进行训练测试,这项工作大概已经有半个多月了,从当初的一无所知,到现在的懵懵懂懂,不知道什么时候才能走到尽头。
网络结构程序就不上了,因为这个自己还没有好好研究透彻,不过后续的性能应该和网络的结构有直接的关系,因此就附上一些自己最近加的训练+测试,以及生成实验结果的程序吧。
深度学习框架:pytorch 1.5.0
训练模块
import torch
import torchvision
import torch.nn as nn
from mobilenetv3 import *
import torch.optim as optim
import torchvision.transforms as transforms
import os
import matplotlib.pyplot as plt
# ----------------------------------------------------------------------------------------------------------------------
# 加载数据
# ----------------------------------------------------------------------------------------------------------------------
def loadtraindata(path):
trainset = torchvision.datasets.ImageFolder(path,
transform=transforms.Compose([
transforms.Resize((224, 224)),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
)
trainloader = torch.utils.data.DataLoader(trainset,
batch_size=10,
shuffle=True,
num_workers=4)
return trainloader
# ----------------------------------------------------------------------------------------------------------------------
# 网络初始化
# ----------------------------------------------------------------------------------------------------------------------
def initialization(path):
if os.path.exists(r'D:\ljc\V3\model\mobilenetv3.pth'):
os.remove(r'D:\ljc\V3\model\mobilenetv3.pth')
net = MobileNetV3_Large()
trainloader = loadtraindata(path)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
return trainloader, device, optimizer, net, criterion
# ----------------------------------------------------------------------------------------------------------------------
# 训练过程
# ----------------------------------------------------------------------------------------------------------------------
def train(trainloader, device, optimizer, net, criterion, ii):
epoch_numbers = 15
Accuracy_list = []
Loss_list = []
for epoch in range(epoch_numbers):# 10次迭代
batch_size = 100 #
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
predict = torch.max(outputs, 1)[1].data.squeeze()
accuracy = (predict == labels).sum().item() / labels.size(0)
print('Energy = %f : [%d, %5d] loss: %.4f accuracy: %.4f ' % (ii, epoch + 1, (i+1)*batch_size, loss.item(), accuracy))
# ----------------------------------------------------------------------------------------------------------------------
print('Energy = %f : Finished Training: epoch %d' % (ii, epoch + 1))
Accuracy_list.append(accuracy)
Loss_list.append(loss)
torch.save(net, './model/mobilenetv3.pth')
x1 = range(1, epoch_numbers+1)
plt.subplot(2, 1, 1)
plt.plot(x1, Accuracy_list, 'o-')
plt.title('Train accuracy vs. epoches')
plt.ylabel('Train accuracy')
plt.subplot(2, 1, 2)
plt.plot(x1, Loss_list, '.-')
plt.title('Train loss vs. epoches')
plt.ylabel('Train loss')
plt.legend()
plt.savefig(str(ii) + "训练情况.jpg")
plt.show()
测试模块
import torchvision.transforms as transforms
from mobilenetv3 import *
from PIL import Image
import imutils
import torch
import cv2
import os
import numpy as np
# ----------------------------------------------------------------------------------------------------------------------
# 初始化网络,恢复参数
# ----------------------------------------------------------------------------------------------------------------------
def initialiazation():
net = MobileNetV3_Large()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
return device
def reload_net(device):
model = torch.load('./model/mobilenetv3.pth', map_location='cpu')
model.to(device)
model.eval()
return model
# ----------------------------------------------------------------------------------------------------------------------
# 图片预处理
# ----------------------------------------------------------------------------------------------------------------------
def pre_process(device):
preprocess_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
net = reload_net(device)
return preprocess_transform,net
# ----------------------------------------------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------------------------------------
# 识别函数
# ----------------------------------------------------------------------------------------------------------------------
def model_test(path, preprocess_transform, device,net):
image = Image.open(path)
image_tensor = preprocess_transform(image).unsqueeze_(0)
outputs = net(image_tensor.to(device))
predict1 = torch.max(outputs, 1)[1]
predict2 = predict1.data
predict3 = predict2.squeeze()
predict = predict3.item()
return predict
# 参考 https://blog.csdn.net/tian_jiangnan/article/details/104047467 python编程之循环遍历文件夹下面的文件,以及获取文件夹名称
def get_pic(path, preprocess_transform, device, net, ii):
# dirs = os.listdir(path) # 返回当前目录下面子目录形成的一个混合信号列表
accu = {
}
y_true = []
y_predict = []
classes = ["BPSK+QPSK", "BPSK+8PSK", "QPSK+8PSK", "BPSK+16QAM", "QPSK+16QAM"]
# for a in dirs:
# classes.append(a)
for a in classes: # 遍历五类混合信号名称的文件夹
average = []
for aa in range(1): # 识别2次 求平均识别率
# print(a)
count = 0
cnt = 0
# print(os.path.isfile(path + "/" + a))
if os.path.isfile(path + "/" + a) != True:
l = os.listdir(path + "/" + a)
l.sort()
for file in l[:200]: # 遍历所有测试图片(200张)
if file.endswith('jpg'):
image_path = path + a + "/" + file
out = model_test(image_path, preprocess_transform, device, net)
# print(classes[out])
if classes[out] == a:
count += 1
y_true.append(classes.index(a))
y_predict.append(out)
cnt += 1
print("snr = " + str(ii) + " : 平均"+ str(aa) +" of 100 正在检测文件夹"+ a + "中第" + str(cnt) + "张图片")
average.append(count/len(l[:200])) # average = [1.0,1.0,1.0,1.0,0.98]
else:
get_pic(str(path) + "/" + a, preprocess_transform, device, ii)
accu[a] = np.mean(average)
return accu, y_true, y_predict
下面是,自己写的 训练+测试 模块
因为深度学习接触不是特别多,所以目前训练和识别的思路,都是自己琢磨出来的,不太知道标不标准,如果有大佬的话,希望可以指点迷津
import run
import test
import time
import numpy as np
if __name__ == '__main__':
time_start = time.asctime(time.localtime(time.time()))
acc = {
}
y_true_list = []
y_predict_list = []
for i in range(-10, 11, 2):
# first train network
train_path = "./data/train/snr/" + str(i) + "/"
[trainloader, device, optimizer, net, criterion] = run.initialization(train_path)
run.train(trainloader, device, optimizer, net, criterion, i)
# second test network
device = test.initialiazation()
[preprocess_transform, net] = test.pre_process(device)
test_path = "./data/test/snr/" + str(i) + "/"
[accu, y_true, y_predict] = test.get_pic(test_path, preprocess_transform, device, net, i)
acc["snr = "+str(i)] = accu
y_true_list.append(y_true)
y_predict_list.append(y_predict)
print(acc)
print(y_true_list)
print(y_predict_list)
print(acc)
print(y_true_list)
print(y_predict_list)
time_end = time.asctime(time.localtime(time.time()))
print("start time:" + time_start)
print("end time:" + time_end)
下面是画出分类以后的混淆矩阵函数
import seaborn as sns
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
def con_matrix(y_true, y_pred, i):
## 输入形式
# y_true = [0, 0, 1, 0, 2]
# y_pred = [0, 0, 0, 0, 1]
sns.set()
f, ax = plt.subplots()
C2 = confusion_matrix(y_true, y_pred, labels=[0, 1, 2, 3, 4])
print(C2) #打印出来看看
label_x = ["BP+QP", "BP+8P", "QP+8P", "BP+16Q", "QP+16Q"]
sns.heatmap(C2, annot=True, ax=ax, xticklabels = label_x,yticklabels = label_x) #画热力图
ax.set_title('confusion matrix') #标题
ax.invert_yaxis()#反转Y坐标轴
ax.set_xlabel('predicted') #x轴
ax.set_ylabel('true') #y轴
plt.savefig(str(i) + 'Confusion_matrix.jpg')
plt.show()
这里是最后一个画图函数,可以生成识别率曲线,混淆矩阵等测试结果
import matplotlib.pyplot as plt
import numpy as np
from confusion_matrix import *
def getAllTypes(res):
## 先取出混合信号的种类list
types = []
for i in res['snr = -10'].keys():#---------------------------------------------------------------------------------------------------------------------
types.append(i)
return types
def getAllData(types, res):
# 输入 types 是混合信号种类的list , res是网络输出的dic
# 输出 包含list的list[[1.0,1.0,1.0],[1.0,1.0,1.0]] 识别率
y = []
num = len(types)
for k in range(num):
yy = []
for kk in res.values():
yy.append(kk[types[k]])
y.append(yy)
return y
def ploter(types, y):
## 输入 types 混合信号的种类 y 就是识别率
##
x = []
## 首先遍历第一层文件夹个数得到五类混合信号的名称---------------------------------------------------------------------------------------------------------------------
for j in range(-10, 11, 2):
x.append(j)
## 对一个文件夹里面的所有信号种类进行画图
for i in range(len(types)):
marks = ['-o', '-s', '-^', '-p', '-^', '-v', '-p', '-d', '-h', '-2', '-8', '-6']
plt.plot(x, y[i], marks[i], label=types[i])
plt.legend()
plt.savefig("Curve_RecognitionRate.jpg")
plt.show()
def integration(result):
## 集成上面所有的函数,just a clik enough
types = getAllTypes(result)
y = getAllData(types, result)
ploter(types, y)
if __name__ == '__main__':
## 1.给出result
integration(result)
## 2.给出y_true,y_pred
con_matrix(y_true, y_pred)
因为只是拿来做实验,跑数据,所有有些地方的逻辑写的有点累赘,灵活性不是很高,每次改的时候总有bug,改好几次才能改到自己的理想结果。 如果有同道中人,希望可以相互学习!!!