炼丹日记

炼丹周记

  • 写在前面: 2020年的最后一个月的第一天
  • 深度学习小白成长之路

写在前面: 2020年的最后一个月的第一天

今天是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,改好几次才能改到自己的理想结果。 如果有同道中人,希望可以相互学习!!!

你可能感兴趣的:(python,深度学习,pytorch,图像识别)