RadioML 2016.10a 调制方式识别

RadioML 2016.10a 调制方式识别 MLP、CNN、ResNet

image-20240619100129670

image-20240619100620198

X = [] 
lbl = []
for mod in mods:
    for snr in snrs:
        X.append(Xd[(mod,snr)])
        for i in range(Xd[(mod,snr)].shape[0]):
            lbl.append((mod,snr))
X = np.vstack(X)
file.close()

image-20240619100632708

上述论文的分类任务是识别和区分不同类型的无线电调制方式。

项目地址:https://github.com/daetz-coder/RadioML2016.10a_CNN

数据链接:https://pan.baidu.com/s/1sxyWf4M0ouAloslcXSJe9w?pwd=2016 
提取码:2016

下面介绍具体的处理方式,首先为了方便数据加载,根据SNR的不同划分为多个csv子文件

import pickle
import pandas as pd

# 指定pickle文件路径
pickle_file_path = './data/RML2016.10a_dict.pkl'

# 加载数据
with open(pickle_file_path, 'rb') as file:
    data_dict = pickle.load(file, encoding='latin1')

# 创建一个字典,用于按SNR组织数据
data_by_snr = {}

# 遍历数据字典,将数据按SNR分组
for key, value in data_dict.items():
    mod_type, snr = key
    if snr not in data_by_snr:
        data_by_snr[snr] = {}
    if mod_type not in data_by_snr[snr]:
        data_by_snr[snr][mod_type] = []
    # 只保留1000条数据
    data_by_snr[snr][mod_type].extend(value[:1000])

# 创建并保存每个SNR对应的CSV文件
for snr, mod_data in data_by_snr.items():
    combined_df = pd.DataFrame()
    for mod_type, samples in mod_data.items():
        for sample in samples:
            flat_sample = sample.flatten()
            temp_df = pd.DataFrame([flat_sample], columns=[f'Sample_{i}' for i in range(flat_sample.size)])
            temp_df['Mod_Type'] = mod_type
            temp_df['SNR'] = snr
            combined_df = pd.concat([combined_df, temp_df], ignore_index=True)
    
    # 保存到CSV文件
    csv_file_path = f'output_data_snr_{snr}.csv'
    combined_df.to_csv(csv_file_path, index=False)
    print(f"CSV file saved for SNR {snr}: {csv_file_path}")

print("Data processing complete. All CSV files saved.")

一、模型划分

0、Baseline

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset, random_split
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# 加载数据
csv_file_path = 'snr_data/output_data_snr_6.csv'
data_frame = pd.read_csv(csv_file_path)

# 提取前256列数据并转换为张量
vectors = torch.tensor(data_frame.iloc[:, :256].values, dtype=torch.float32)

# 划分训练集和测试集索引
train_size = int(0.8 * len(vectors))
test_size = len(vectors) - train_size
train_indices, test_indices = random_split(range(len(vectors)), [train_size, test_size])

# 使用训练集的统计量进行归一化
train_vectors = vectors[train_indices]
train_mean = train_vectors.mean(dim=0, keepdim=True)
train_std = train_vectors.std(dim=0, keepdim=True)

vectors = (vectors - train_mean) / train_std

# 转置和重塑为16x16 若MLP 无需重构
vectors = vectors.view(-1, 16, 16).unsqueeze(1).permute(0, 1, 3, 2)  # 添加通道维度并进行转置


# 提取Mod_Type列并转换为数值标签
mod_types = data_frame['Mod_Type'].astype('category').cat.codes.values
labels = torch.tensor(mod_types, dtype=torch.long)

# 创建TensorDataset
dataset = TensorDataset(vectors, labels)

# 创建训练集和测试集
train_dataset = TensorDataset(vectors[train_indices], labels[train_indices])
test_dataset = TensorDataset(vectors[test_indices], labels[test_indices])

# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

这里需要加载具体模型

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
num_epochs = 100
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []

def calculate_accuracy(outputs, labels):
    _, predicted = torch.max(outputs, 1)
    total = labels.size(0)
    correct = (predicted == labels).sum().item()
    return correct / total

for epoch in range(num_epochs):
    # 训练阶段
    model.train()
    running_loss = 0.0
    correct = 0
    total = 0
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        correct += (outputs.argmax(1) == labels).sum().item()
        total += labels.size(0)
    train_loss = running_loss / len(train_loader)
    train_accuracy = correct / total
    train_losses.append(train_loss)
    train_accuracies.append(train_accuracy)
    
    # 测试阶段
    model.eval()
    running_loss = 0.0
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in test_loader:
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            running_loss += loss.item()
            correct += (outputs.argmax(1) == labels).sum().item()
            total += labels.size(0)
    test_loss = running_loss / len(test_loader)
    test_accuracy = correct / total
    test_losses.append(test_loss)
    test_accuracies.append(test_accuracy)
    
    print(f"Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")

print("Training complete.")

image-20240619123116251

# 计算混淆矩阵
all_labels = []
all_predictions = []

model.eval()
with torch.no_grad():
    for inputs, labels in test_loader:
        outputs = model(inputs)
        _, predicted = torch.max(outputs, 1)
        all_labels.extend(labels.numpy())
        all_predictions.extend(predicted.numpy())

# 绘制混淆矩阵
cm = confusion_matrix(all_labels, all_predictions)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=data_frame['Mod_Type'].astype('category').cat.categories)
disp.plot(cmap=plt.cm.Blues)
plt.show()

1、MLP

from torchinfo import summary
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(256, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 11)  # 有11种调制类型

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

model = SimpleNN()
# 打印模型结构和参数
summary(model, input_size=(1, 256))

image-20240619122355039

image-20240619122600032

image-20240619122623890

2、CNN

# 定义模型
from torchinfo import summary
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(16)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(32)
        self.dropout = nn.Dropout(0.3)
        self.fc1 = nn.Linear(32*4*4, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 11)  # 11种调制类型

    def forward(self, x):
        x = torch.relu(self.bn1(self.conv1(x)))
        x = torch.max_pool2d(x, 2)
        x = torch.relu(self.bn2(self.conv2(x)))
        x = torch.max_pool2d(x, 2)
        x = x.view(x.size(0), -1)
        x = torch.relu(self.fc1(x))
        x = self.dropout(x)
        x = torch.relu(self.fc2(x))
        x = self.dropout(x)
        x = self.fc3(x)
        return x

model = SimpleCNN()
summary(model, input_size=(1, 1,16,16))

image-20240619122341650

image-20240619122652005

image-20240619122657948

3、ResNet

# 定义ResNet基本块
from torchinfo import summary
class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, in_planes, planes, stride=1):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion * planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion * planes)
            )

    def forward(self, x):
        out = torch.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = torch.relu(out)
        return out

# 定义ResNet
class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=11):
        super(ResNet, self).__init__()
        self.in_planes = 16

        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(16)
        self.layer1 = self._make_layer(block, 16, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 32, num_blocks[1], stride=2)
        self.linear = nn.Linear(32*4*4*4, num_classes)

    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = torch.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = torch.flatten(out, 1)
        out = self.linear(out)
        return out

def ResNet18():
    return ResNet(BasicBlock, [2, 2])

model = ResNet18()
summary(model, input_size=(1, 1,16,16))

image-20240619122312714

image-20240619122714985

image-20240619122722813

可以发现在三种模型下非常容易过拟合,为了探究是否是SNR的造成的影响,故修改SNR数值,进行下述实验

二、SNR划分

根据SNR的计算公式来看,-20db表示噪声的功率是信号的100倍,其余以此类推

image-20240619125247448

1、SNR(-20) min

image-20240619125210047

image-20240619125216547

image-20240619125223002

2、SNR(-6)

image-20240619125029174

image-20240619124938229

image-20240619124944334

3、SNR(0)

image-20240619125019091

image-20240619124959152

image-20240619125006416

4、SNR(6)

image-20240619125047770

image-20240619125110720

image-20240619125117493

5、SNR(18) max

image-20240619125138169

image-20240619125145635

image-20240619125151302

从实验结果来看,趋势还是比较符合预期,总体上SNR越大检测的性能越好,尤其是当SNR=-20db时无法区分任何一种类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/723312.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

收藏这几个电子书搜索引擎网站,找书不再难!

书籍是我们快速学习获取知识的重要途径,其中,通过电子书学习是一种低成本的学习方式。然而,面对海量的电子书资源,如何快速找到自己想要的书籍呢?下面小编就来为大家介绍几个强大的电子书搜索引擎网站,帮助…

数字时代的创新:二人共益订单模式解析

一、引言 随着数字技术的飞速发展,商业模式也日新月异。其中,“二人共益订单模式”凭借其独特的互助与共赢理念,迅速在市场中获得关注。该模式不仅为用户提供了优质服务和独享优惠,更通过用户间的互助和订单共享,实现…

AbMole带你探索颅内压力与肌肉生长的联系:一项突破性研究

在生物医学领域,颅内压力(ICP)的调控机制一直是研究的热点。最近,一项发表在《PLOS ONE》上的研究为我们揭示了颅内压力与后颅窝肌肉生长之间的潜在联系,为我们理解某些慢性头痛的成因提供了新的视角。 颅内压力的异常…

期望25K,我的React知识体系

面经哥只做互联网社招面试经历分享,关注我,每日推送精选面经,面试前,先找面经哥 我最终还是上岸了,花了3天总结了近万字的react知识体系思维导图,分享出来希望能帮助有缘人吧,以下只是部分截图&…

goldfish loss:减少训练数据泄漏,提高大语言模型输出的多样性

LLMs(大型语言模型)能够记忆并重复它们的训练数据,这可能会带来隐私和版权风险。为了减轻记忆现象,论文作者引入了一种名为"goldfish loss"的微妙修改,在训练过程中,随机抽样的一部分标记被排除在…

美国ARC与延锋安全合作,推动汽车安全气囊技术新突破

在汽车安全领域,安全气囊作为关键被动安全配置,对于保障乘客生命安全至关重要。随着汽车工业的快速发展和科技创新的持续推进,安全气囊技术的升级与革新显得尤为重要。2022年10月25日,美国ARC公司与延锋安全携手合作,共…

4大利好因素释放顺风车市场潜力,嘀嗒出行即将登陆港交所

经历了十多年发展,共享出行行业即将迎来第一个上市公司——专注顺风车和智慧出租车的嘀嗒出行。 近日,嘀嗒出行通过了港交所聆讯,根据招股书,嘀嗒出行2023年顺风车搭乘次数和交易额分别为约1.3亿次和86亿元,同比分别增…

CCS条形光源——HLDL3系列,长距离和宽范围照射应用的不二之选

机器视觉系统中,光源起着重要作用,不同类型的光源应用也不同,选择合适的光源成像效果非常明显。今天我们一起来看看CCS光源——工业用条形光源HLDL3系列。 高亮LED光源HLDL3系列 适用于长距离和宽范围照射的条形光源。 适用于各种检测案例&a…

Jenkins+K8s实现持续集成(三)

接上面一篇JenkinsK8s实现持续集成(二),K8s创建秘钥。 看secret kubectl get secret 删除secret kubectl delete secret hello-secret -n train 创建secret kubectl create secret docker-registry hello-secret --docker-server镜像仓库…

安卓怎么传输数据到新苹果手机?2招制胜,玩转新手机

当你手中紧握着最新款的苹果手机,心中充满了对科技新宠的期待与好奇,却发现旧手机里的数据如同搬家时的宝贝,怎么也舍不得丢。安卓怎么传输数据到新苹果手机?今天我们就来解锁安卓到苹果数据传输的秘密,让你轻松实现数…

聊聊redis中的有序集合

写在文章开头 有序集合(sorted set)是redis中比较常见的数据库结构,它不仅支持O(logN)界别的有序的范围查询,同时也支持O(1)级别的单元素查询,基于此问题,本文就将从redis源码的角度分析一下有序集合的设计与实现。 Hi&#xff0…

Vue3【二十二】Vue 路由模式的嵌套路由和用query给组件的RouterLink传参

Vue3【二十二】Vue 路由模式的嵌套路由和用query给组件传参 Vue3【二十二】Vue 路由模式的嵌套路由和用query给组件传参 RouterLink 的两种传参方法 RouterView 案例截图 目录结构 代码 index.ts // 创建一个路由器,并暴漏出去// 第一步:引入createRou…

ATA-4011C高压功率放大器在亥姆霍兹线圈中的作用介绍

高压功率放大器在亥姆霍兹线圈中的作用是为亥姆霍兹线圈提供稳定的高功率电流信号,从而产生强大的磁场。亥姆霍兹线圈是一种用于产生均匀磁场的设备,在物理实验、医学成像和工业领域中得到广泛应用。下面安泰电子官网将从以下几个方面详细介绍高压功率放…

推荐阅读:车载测试新纪元,智能座舱的全面解读

前段时间给自己定了一个计划,决定来学一下车载测试的相关内容,既然车载测试被大家说的这么火,作为一个测试人员,不去了解一下怎么行呢?当然,目前的行业还可以咯,但是给自己适当的投资充电&#…

国际荐酒师携手各国际荐酒师专业委员会深化2024年度合作

国际荐酒师(香港)协会携手广东海上丝绸之路文化促进会及广东省城镇化发展研究会,深化2024年度合作,共同打造品荐与传播大师班培养荐酒师专业人材 近日,国际荐酒师(香港)协会、广东海上丝绸之路…

『Z-Weekly Feed 08』加密资产观 | FHE应用前景 | OPAL协议

一位机构投资者的加密资产观 作者:Hongbo 01 💡TL;DR 在加密投资领域如何找到真正的“价值”:Crypto 作为一种新兴资产,应该找到一种区别于传统公司股票资产的估值方法,本文重点阐述了加密货币作为新的资产类型与传统资…

康谋分享 | 从CAN到CAN FD:ADTF在汽车网络中的应用

随着汽车电子技术的发展,车辆上配备了越来越多的电子装置,这些设备多采用点对点的方式通信,这也导致了车内存在庞大的线束。造成汽车制造和安装的困难并进一步降低汽车的配置空间,汽车总线逐步开始向网络化方向发展。 在此背景下…

FANUC喷涂机器人P-350iA电机过热维修解决方案

发那科喷涂机器人作为自动化喷涂生产线的重要组成部分,其性能稳定性和可靠性对于生产效率和产品质量具有重要影响。然而,在实际使用过程中,FANUC喷涂机器人P-350iA电机过热故障问题往往成为影响其正常运行的主要因素之一。 FANUC机器人M-100…

第一百一十二节 Java面向对象设计 - Java异常处理

Java面向对象设计 - Java异常处理 异常是在没有定义正常执行路径时在Java程序的执行期间可能出现的条件。 Java通过将执行操作的代码与处理错误的代码分离来处理错误。 当发生异常时,Java会创建一个包含有关异常的所有信息的对象,并将其传递给相应的异…

阿里云ECS(CentOS/Alibaba Cloud Linux)安装最新 Docker 方法

最近(6月份)我发现 docker 官方无法正常访问,docker pull 命令也执行失败,用 TZ 也一样😔。 以下步骤适用于 CentOS 7/8或Alibaba Cloud Linux 系统。 1. 更新系统包 首先,确保您的ECS实例系统软件包是最…