数据集生成源代码(需要GNU Radio来实现,如需安装学习参考主页相关教程)
链接: https://github.com/radioML/dataset
现成的数据集下载(来自DeepSig公司主页)
链接: https://www.deepsig.ai/datasets
一般来说,RADIOML 2016.10A就可以满足需求,其他数据集将消耗更大的硬件需求。
链接: https://arxiv.org/abs/1602.04105
1.tensorflow2,keras2
2.gpu:RTX3080Ti,cpu:Intel Xeon E5-2690 v4
(1)导包,本来我是tf2,后来为了适应tf1版本,加了几行代码,现在tf1应该可以用。
from tensorflow.compat.v1 import ConfigProto
from tensorflow.compat.v1 import InteractiveSession
config = ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)
import h5py
import numpy as np
#import theano as th
import os,random
import pickle,random, sys
import tensorflow as tf
tf.compat.v1.enable_eager_execution()
from tensorflow import keras
import matplotlib.pyplot as plt
import gc
from tensorflow.keras.layers import Reshape,Dense,Dropout,Activation,Flatten,Convolution2D, MaxPooling2D, ZeroPadding2D,LSTM
%matplotlib inline
#os.environ["KERAS_BACKEND"] = "tensorflow"
os.environ["THEANO_FLAGS"] = "device=gpu%d"%(0)
(2)导入数据集,X是数据,lbl是标签(包含调制类型和信噪比)
Xd = pickle.load(open("RML2016.10a_dict.pkl",'rb'),encoding='latin1')
#data=pk.load(f,encoding='latin1')
#print(data)
snrs,mods = map(lambda j: sorted(list(set(map(lambda x: x[j], Xd.keys())))), [1,0])
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)
(3)划分训练集和数据集,to_onehot打标签
np.random.seed(2016)
n_examples = X.shape[0]
n_train = int(n_examples*0.8)
train_idx = np.random.choice(range(0,n_examples), size=n_train, replace=False)
test_idx = list(set(range(0,n_examples))-set(train_idx))
X_train = X[train_idx]
X_test = X[test_idx]
def to_onehot(yy):
yy1 = np.zeros([len(yy), max(yy)+1])
yy1[np.arange(len(yy)),yy] = 1
return yy1
Y_train = to_onehot(list(map(lambda x: mods.index(lbl[x][0]), train_idx)))
Y_test = to_onehot(list(map(lambda x: mods.index(lbl[x][0]), test_idx)))
in_shp = list(X_train.shape[1:])
print (X_train.shape, in_shp)
classes = mods
print('数据集总数:',n_examples)
print('调制方式' , len(mods),'种:' ,mods)
print('信噪比:',snrs)
(4)神经网络结构
dr = 0.5 # dropout rate (%)
lstm_output_size=512
model = keras.Sequential()
model.add(Reshape(in_shp+[1], input_shape=in_shp))
model.add(ZeroPadding2D(padding=(0,2)))
model.add(Convolution2D(256, (1,3), padding='valid', activation="relu", name="conv1"))
model.add(Dropout(dr))
model.add(ZeroPadding2D(padding=(0, 2)))
model.add(Convolution2D(80, (2, 3), padding="valid", activation="relu", name="conv2"))
model.add(Dropout(dr))
model.add(Flatten())
model.add(Dense(1024, activation='relu', name="dense1"))
model.add(Dense(256, activation='relu', name="dense1"))
model.add(Dropout(dr))
model.add(Dense( len(classes), name="dense2" ))
model.add(Activation('softmax'))
model.add(Reshape([len(classes)]))
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=["accuracy"])
model.summary()
(5)训练,引入了早停法
# Set up some params
epochs = 100 # number of epochs to train on
batch_size = 1024 # training batch size
# - call the main training loop in keras for our network+dataset
filepath = 'conv.h5'
history = model.fit(X_train,
Y_train,
batch_size=batch_size,
epochs=epochs,
verbose=2,
validation_data=(X_test, Y_test),
callbacks = [
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=True, mode='auto'),
keras.callbacks.EarlyStopping(monitor='val_loss', patience=5, verbose=0, mode='auto')
])
# we re-load the best weights once training is finished
model.load_weights(filepath)
(6)记录并绘制损失曲线
score = model.evaluate(X_test, Y_test, batch_size=batch_size,verbose=0)
print (score)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
(7)绘制混淆矩阵
def plot_confusion_matrix(cm, title='Confusion matrix', cmap=plt.cm.Blues, labels=[]):
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(labels))
plt.xticks(tick_marks, labels, rotation=45)
plt.yticks(tick_marks, labels)
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label'
# Plot confusion matrix
test_Y_hat = model.predict(X_test, batch_size=batch_size)
conf = np.zeros([len(classes),len(classes)])
confnorm = np.zeros([len(classes),len(classes)])
for i in range(0,X_test.shape[0]):
j = list(Y_test[i,:]).index(1)
k = int(np.argmax(test_Y_hat[i,:]))
conf[j,k] = conf[j,k] + 1
for i in range(0,len(classes)):
confnorm[i,:] = conf[i,:] / np.sum(conf[i,:])
plot_confusion_matrix(confnorm, labels=classes)
# Plot confusion matrix
acc = {}
for snr in snrs:
# extract classes @ SNR
test_SNRs = list(map(lambda x: lbl[x][1], test_idx))#map在tensorflow2中前面要加list
test_X_i = X_test[np.where(np.array(test_SNRs)==snr)]
test_Y_i = Y_test[np.where(np.array(test_SNRs)==snr)]
# estimate classes
test_Y_i_hat = model.predict(test_X_i)
conf = np.zeros([len(classes),len(classes)])
confnorm = np.zeros([len(classes),len(classes)])
for i in range(0,test_X_i.shape[0]):
j = list(test_Y_i[i,:]).index(1)
k = int(np.argmax(test_Y_i_hat[i,:]))
conf[j,k] = conf[j,k] + 1
for i in range(0,len(classes)):
confnorm[i,:] = conf[i,:] / np.sum(conf[i,:])
plt.figure()
plot_confusion_matrix(confnorm, labels=classes, title="ConvNet Confusion Matrix (SNR=%d)"%(snr))
cor = np.sum(np.diag(conf))
ncor = np.sum(conf) - cor
print ("Overall Accuracy: ", cor / (cor+ncor))
acc[snr] = 1.0*cor/(cor+ncor)
(8)绘制信噪比曲线
# Save results to a pickle file for plotting later
print (acc)
fd = open('results_cnn.dat','wb')
pickle.dump( ("CNN2", 0.5, acc) , fd )
# Plot accuracy curve
plt.plot(snrs, list(map(lambda x: acc[x], snrs)))
plt.xlabel('Signal to Noise Ratio')
plt.ylabel('Classification Accuracy')
plt.title("CNN2 Classification Accuracy on RadioML 2016.10 Alpha")
更多调制识别论文的复现论文将陆陆续续发布!