diff --git a/.gitignore b/.gitignore
index 6a6079e26d075b0f1974be75f44795703c579fae..f5a232a4e47e3125fb60cce11ae3ccb403883149 100644
--- a/.gitignore
+++ b/.gitignore
@@ -138,5 +138,4 @@ dmypy.json
/train_backup.py
*.pth
*.edf
-*log*
-*.png
\ No newline at end of file
+*log*
\ No newline at end of file
diff --git a/README.md b/README.md
index e4300f55ef6ed70d8cb83f6d59492f4aa9bf2419..cb0be172adb40811c81037d3e5bf2e7539090cba 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,27 @@
+
+
+
# candock
-[这原本是一个用于记录毕业设计的日志仓库](),其目的是尝试多种不同的深度神经网络结构(如LSTM,ResNet,DFCNN等)对单通道EEG进行自动化睡眠阶段分期.
目前,项目重点将转变为如何建立一个通用的一维时序信号分析,分类框架.
它将包含多种网络结构,并提供数据预处理,读取,训练,评估,测试等功能.
-一些训练时的输出样例: [heatmap](./image/heatmap_eg.png) [running_err](./image/running_err_eg.png) [log.txt](./docs/log_eg.txt)
+| English | [中文版](./README_CN.md) |
+A time series signal analysis and classification framework.
+It contain multiple network and provide data preprocessing, reading, training, evaluation, testing and other functions.
+Some output examples: [heatmap](./image/heatmap_eg.png) [running_err](./image/running_err_eg.png) [log.txt](./docs/log_eg.txt)
Supported network:
-## 注意
-为了适应新的项目,代码已被大幅更改,不能确保仍然能正常运行如sleep-edfx等睡眠数据集,如果仍然需要运行,请参照下文按照输入格式标准自行加载数据,如果有时间我会修复这个问题。
-当然,如果需要加载睡眠数据集也可以直接使用[老的版本](https://github.com/HypoX64/candock/tree/f24cc44933f494d2235b3bf965a04cde5e6a1ae9)
-感谢[@swalltail99](https://github.com/swalltail99)指出的错误,为了适应sleep-edfx数据集的读取,使用这个版本的代码时,请安装mne==0.18.0
+>1d
+>
+>>lstm, cnn_1d, resnet18_1d, resnet34_1d, multi_scale_resnet_1d, micro_multi_scale_resnet_1d
+
+>2d(stft spectrum)
+>
+>>mobilenet, resnet18, resnet50, resnet101, densenet121, densenet201, squeezenet, dfcnn, multi_scale_resnet,
+
+## A example: Use EEG to classify sleep stage
+[sleep-edfx](https://github.com/HypoX64/candock/tree/f24cc44933f494d2235b3bf965a04cde5e6a1ae9)
+Thank [@swalltail99](https://github.com/swalltail99)for the bug. In other to load sleep-edfx dataset,please install mne==0.18.0
```bash
pip install mne==0.18.0
```
-
## Getting Started
### Prerequisites
- Linux, Windows,mac
@@ -18,7 +29,7 @@ pip install mne==0.18.0
- Python 3
- Pytroch 1.0+
### Dependencies
-This code depends on torchvision, numpy, scipy , matplotlib,available via pip install.
+This code depends on torchvision, numpy, scipy , matplotlib, available via pip install.
For example:
```bash
@@ -41,7 +52,13 @@ python3 train.py --label 50 --input_nc 1 --dataset_dir ./datasets/simple_test --
# if you want to use cpu to train, please input --gpu_id -1
```
* More [options](./util/options.py).
-#### Use your own data to train
+### Test
+```bash
+python3 simple_test.py --label 50 --input_nc 1 --model_name micro_multi_scale_resnet_1d --gpu_id 0
+# if you want to use cpu to test, please input --gpu_id -1
+```
+
+## Training with your own dataset
* step1: Generate signals.npy and labels.npy in the following format.
```python
#1.type:numpydata signals:np.float64 labels:np.int64
@@ -51,10 +68,5 @@ python3 train.py --label 50 --input_nc 1 --dataset_dir ./datasets/simple_test --
signals = np.zeros((10,1,10),dtype='np.float64')
labels = np.array([0,0,0,0,0,1,1,1,1,1]) #0->class0 1->class1
```
-* step2: input ```--dataset_dir your_dataset_dir``` when running code.
-### Test
-```bash
-python3 simple_test.py --label 50 --input_nc 1 --model_name micro_multi_scale_resnet_1d --gpu_id 0
-# if you want to use cpu to test, please input --gpu_id -1
-```
+* step2: input ```--dataset_dir "your_dataset_dir"``` when running code.
diff --git a/README_CN.md b/README_CN.md
new file mode 100644
index 0000000000000000000000000000000000000000..5b46cbb98ac816ed2038449fd7b82ede85003d9b
--- /dev/null
+++ b/README_CN.md
@@ -0,0 +1,75 @@
+
+
+
+# candock
+| [English](./README.md) | 中文版 |
+一个通用的一维时序信号分析,分类框架.
+它将包含多种网络结构,并提供数据预处理,读取,训练,评估,测试等功能.
+一些训练时的输出样例: [heatmap](./image/heatmap_eg.png) [running_err](./image/running_err_eg.png) [log.txt](./docs/log_eg.txt)
+目前支持的网络结构:
+>1d
+>
+>>lstm, cnn_1d, resnet18_1d, resnet34_1d, multi_scale_resnet_1d, micro_multi_scale_resnet_1d
+
+
+>2d(stft spectrum)
+>
+>>mobilenet, resnet18, resnet50, resnet101, densenet121, densenet201, squeezenet, dfcnn, multi_scale_resnet,
+
+## 关于EEG睡眠分期数据的实例
+为了适应新的项目,代码已被大幅更改,不能正常运行如sleep-edfx等睡眠数据集,如果仍然需要运行,请参照下文按照输入格式标准自行加载数据,如果有时间我会修复这个问题。
+当然,如果需要加载睡眠数据集也可以直接使用[老的版本](https://github.com/HypoX64/candock/tree/f24cc44933f494d2235b3bf965a04cde5e6a1ae9)
+感谢[@swalltail99](https://github.com/swalltail99)指出的错误,为了适应sleep-edfx数据集的读取,使用这个版本的代码时,请安装mne==0.18.0
+
+```bash
+pip install mne==0.18.0
+```
+
+## 入门
+### 前提要求
+- Linux, Windows,mac
+- CPU or NVIDIA GPU + CUDA CuDNN
+- Python 3
+- Pytroch 1.0+
+### 依赖
+This code depends on torchvision, numpy, scipy , matplotlib, available via pip install.
+For example:
+
+```bash
+pip3 install matplotlib
+```
+### 克隆仓库:
+```bash
+git clone https://github.com/HypoX64/candock
+cd candock
+```
+### 下载数据集以及预训练模型
+[[Google Drive]](https://drive.google.com/open?id=1NTtLmT02jqlc81lhtzQ7GlPK8epuHfU5) [[百度云,y4ks]](https://pan.baidu.com/s/1WKWZL91SekrSlhOoEC1bQA)
+
+* 数据集包括 signals.npy(shape:18207, 1, 2000) 以及 labels.npy(shape:18207) 可以使用"np.load()"加载
+* 样本量:18207, 通道数:1, 每个样本的长度:2000, 总类别数:50
+* Top1 err: 2.09%
+### 训练
+```bash
+python3 train.py --label 50 --input_nc 1 --dataset_dir ./datasets/simple_test --save_dir ./checkpoints/simple_test --model_name micro_multi_scale_resnet_1d --gpu_id 0 --batchsize 64 --k_fold 5
+# 如果需要使用cpu进行训练, 请输入 --gpu_id -1
+```
+* 更多可选参数 [options](./util/options.py).
+### 测试
+```bash
+python3 simple_test.py --label 50 --input_nc 1 --model_name micro_multi_scale_resnet_1d --gpu_id 0
+# 如果需要使用cpu进行训练, 请输入 --gpu_id -1
+```
+
+## 使用自己的数据进行训练
+* step1: 按照如下格式生成 signals.npy 以及 labels.npy.
+```python
+#1.type:numpydata signals:np.float64 labels:np.int64
+#2.shape signals:[num,ch,length] labels:[num]
+#num:samples_num, ch :channel_num, num:length of each sample
+#for example:
+signals = np.zeros((10,1,10),dtype='np.float64')
+labels = np.array([0,0,0,0,0,1,1,1,1,1]) #0->class0 1->class1
+```
+* step2: 输入 ```--dataset_dir "your_dataset_dir"``` 当运行代码的时候.
+
diff --git a/image/compare.png b/imgs/compare.png
similarity index 100%
rename from image/compare.png
rename to imgs/compare.png
diff --git a/image/heatmap_eg.png b/imgs/heatmap_eg.png
similarity index 100%
rename from image/heatmap_eg.png
rename to imgs/heatmap_eg.png
diff --git a/image/multi_scale_resnet_1d_network.png b/imgs/multi_scale_resnet_1d_network.png
similarity index 100%
rename from image/multi_scale_resnet_1d_network.png
rename to imgs/multi_scale_resnet_1d_network.png
diff --git a/image/running_err_eg.png b/imgs/running_err_eg.png
similarity index 100%
rename from image/running_err_eg.png
rename to imgs/running_err_eg.png
diff --git a/image/spectrum_REM.png b/imgs/spectrum_REM.png
similarity index 100%
rename from image/spectrum_REM.png
rename to imgs/spectrum_REM.png
diff --git a/image/spectrum_Stage1.png b/imgs/spectrum_Stage1.png
similarity index 100%
rename from image/spectrum_Stage1.png
rename to imgs/spectrum_Stage1.png
diff --git a/image/spectrum_Stage2.png b/imgs/spectrum_Stage2.png
similarity index 100%
rename from image/spectrum_Stage2.png
rename to imgs/spectrum_Stage2.png
diff --git a/image/spectrum_Stage3.png b/imgs/spectrum_Stage3.png
similarity index 100%
rename from image/spectrum_Stage3.png
rename to imgs/spectrum_Stage3.png
diff --git a/image/spectrum_Wake.png b/imgs/spectrum_Wake.png
similarity index 100%
rename from image/spectrum_Wake.png
rename to imgs/spectrum_Wake.png
diff --git a/models/core.py b/models/core.py
index 911a18a09008fdda18341521f405c6e235c56b95..1b7a2697b6b792b50463439f737bf47f19597446 100644
--- a/models/core.py
+++ b/models/core.py
@@ -37,7 +37,7 @@ class Core(object):
self.criterion_class = nn.CrossEntropyLoss(self.opt.weight)
self.criterion_auto = nn.MSELoss()
self.epoch = 1
- self.plot_result = {'train':[],'eval':[]}
+ self.plot_result = {'train':[],'eval':[],'F1':[]}
self.confusion_mats = []
self.test_flag = True
@@ -145,13 +145,14 @@ class Core(object):
signal,label = self.queue.get()
signal,label = transformer.ToTensor(signal,label,gpu_id =self.opt.gpu_id)
with torch.no_grad():
- loss,features,confusion_mat=self.forward(signal, label, features, confusion_mat)
+ loss,features,confusion_mat = self.forward(signal, label, features, confusion_mat)
epoch_loss += loss.item()
if self.opt.model_name != 'autoencoder':
recall,acc,sp,err,k = statistics.report(confusion_mat)
#plot.draw_heatmap(confusion_mat,self.opt,name = 'current_eval')
print('epoch:'+str(self.epoch),' macro-prec,reca,F1,err,kappa: '+str(statistics.report(confusion_mat)))
+ self.plot_result['F1'].append(statistics.report(confusion_mat)[2])
else:
plot.draw_autoencoder_result(signal.data.cpu().numpy(), out.data.cpu().numpy(),self.opt)
print('epoch:'+str(self.epoch),' loss: '+str(round(epoch_loss/i,5)))
diff --git a/models/creatnet.py b/models/creatnet.py
index 8d0a258dbc7fe20ca0dd42224d9d89ee4fd99557..604d3fd2f88e4ae420099b0facf04223dec9e837 100644
--- a/models/creatnet.py
+++ b/models/creatnet.py
@@ -30,9 +30,10 @@ def creatnet(opt):
#---------------------------------2d---------------------------------
elif name == 'dfcnn':
- net = dfcnn.dfcnn(num_classes = opt.label)
+ net = dfcnn.dfcnn(num_classes = opt.label, input_nc = opt.input_nc)
elif name == 'multi_scale_resnet':
- net = multi_scale_resnet.Multi_Scale_ResNet(inchannel=opt.input_nc, num_classes=opt.label)
+ net = multi_scale_resnet.Multi_Scale_ResNet(input_nc = opt.input_nc, num_classes=opt.label)
+
elif name in ['resnet101','resnet50','resnet18']:
if name =='resnet101':
net = resnet.resnet101(pretrained=True)
@@ -47,10 +48,14 @@ def creatnet(opt):
elif 'densenet' in name:
if name =='densenet121':
- net = densenet.densenet121(pretrained=True,num_classes=opt.label)
+ net = densenet.densenet121(pretrained=False,num_classes = opt.label)
elif name == 'densenet201':
- net = densenet.densenet201(pretrained=True,num_classes=opt.label)
- elif name =='squeezenet':
- net = squeezenet.squeezenet1_1(pretrained=True,num_classes=opt.label,inchannel = 1)
+ net = densenet.densenet201(pretrained=False,num_classes = opt.label)
+ net.features.conv0 = nn.Conv2d(opt.input_nc, 64, kernel_size=7, stride=2, padding=3, bias=False)
+
+ elif name == 'squeezenet':
+ net = squeezenet.squeezenet1_1(pretrained=False,num_classes = opt.label,inchannel = opt.input_nc)
+ elif name == 'mobilenet':
+ net = mobilenet.mobilenet_v2(pretrained=False, num_classes = opt.label, input_nc = opt.input_nc)
return net
\ No newline at end of file
diff --git a/models/net_2d/densenet.py b/models/net_2d/densenet.py
index 65029a9f0e8e80e811025406f61cb73afb8123e1..5ef85f3162cf7603ba53c574edfad1ee203c4330 100644
--- a/models/net_2d/densenet.py
+++ b/models/net_2d/densenet.py
@@ -75,7 +75,7 @@ class DenseNet(nn.Module):
# First convolution
self.features = nn.Sequential(OrderedDict([
- ('conv0', nn.Conv2d(1, num_init_features, kernel_size=7, stride=2, padding=3, bias=False)),
+ ('conv0', nn.Conv2d(3, num_init_features, kernel_size=7, stride=2, padding=3, bias=False)),
('norm0', nn.BatchNorm2d(num_init_features)),
('relu0', nn.ReLU(inplace=True)),
('pool0', nn.MaxPool2d(kernel_size=3, stride=2, padding=1)),
diff --git a/models/net_2d/dfcnn.py b/models/net_2d/dfcnn.py
index 365f7fb24b2f353e7e6d95a0baaef6391301bc55..3ee00ddc471203359aa10058351302b7ef072a50 100644
--- a/models/net_2d/dfcnn.py
+++ b/models/net_2d/dfcnn.py
@@ -4,10 +4,10 @@ import torch.nn.functional as F
class dfcnn(nn.Module):
- def __init__(self, num_classes):
+ def __init__(self, num_classes, input_nc):
super(dfcnn, self).__init__()
self.layer1 = nn.Sequential(
- nn.Conv2d(1, 32, 3, 1, 1, bias=False),
+ nn.Conv2d(input_nc, 32, 3, 1, 1, bias=False),
nn.BatchNorm2d(32),
nn.ReLU(inplace = True),
nn.Conv2d(32, 32, 3, 1, 1, bias=False),
diff --git a/models/net_2d/mobilenet.py b/models/net_2d/mobilenet.py
index 6ce81cb78902be004a525baa7318c598ea1b623f..c23c87b6360a8f58363368993ab4901898850819 100644
--- a/models/net_2d/mobilenet.py
+++ b/models/net_2d/mobilenet.py
@@ -42,7 +42,7 @@ class InvertedResidual(nn.Module):
class MobileNetV2(nn.Module):
- def __init__(self, num_classes=1000, width_mult=1.0):
+ def __init__(self, num_classes=1000, input_nc=3, width_mult=1.0):
super(MobileNetV2, self).__init__()
block = InvertedResidual
input_channel = 32
@@ -61,7 +61,7 @@ class MobileNetV2(nn.Module):
# building first layer
input_channel = int(input_channel * width_mult)
self.last_channel = int(last_channel * max(1.0, width_mult))
- features = [ConvBNReLU(3, input_channel, stride=2)]
+ features = [ConvBNReLU(input_nc, input_channel, stride=2)]
# building inverted residual blocks
for t, c, n, s in inverted_residual_setting:
output_channel = int(c * width_mult)
diff --git a/models/net_2d/multi_scale_resnet.py b/models/net_2d/multi_scale_resnet.py
index f7927b2076f8250f1103140fe1c793156f909101..64a0cff3bdf2dcd3772fd86357a87a6ddf7baf9f 100644
--- a/models/net_2d/multi_scale_resnet.py
+++ b/models/net_2d/multi_scale_resnet.py
@@ -2,18 +2,18 @@ import torch
from torch import nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
- def __init__(self, inchannel, outchannel,kernel_size,stride=2):
+ def __init__(self, input_nc, outchannel,kernel_size,stride=2):
super(ResidualBlock, self).__init__()
self.stride = stride
self.conv = nn.Sequential(
- nn.Conv2d(inchannel, outchannel, kernel_size=kernel_size, stride=stride, padding=int((kernel_size-1)/2), bias=False),
+ nn.Conv2d(input_nc, outchannel, kernel_size=kernel_size, stride=stride, padding=int((kernel_size-1)/2), bias=False),
nn.BatchNorm2d(outchannel),
nn.ReLU(inplace=True),
nn.Conv2d(outchannel, outchannel, kernel_size=kernel_size, stride=1, padding=int((kernel_size-1)/2), bias=False),
nn.BatchNorm2d(outchannel)
)
self.shortcut = nn.Sequential(
- nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=2, bias=False),
+ nn.Conv2d(input_nc, outchannel, kernel_size=1, stride=2, bias=False),
nn.BatchNorm2d(outchannel)
)
@@ -42,10 +42,10 @@ class Route(nn.Module):
return x
class Multi_Scale_ResNet(nn.Module):
- def __init__(self, inchannel, num_classes):
+ def __init__(self, input_nc, num_classes):
super(Multi_Scale_ResNet, self).__init__()
self.pre_conv = nn.Sequential(
- nn.Conv2d(inchannel, 64, kernel_size=7, stride=2, padding=3, bias=False),
+ nn.Conv2d(input_nc, 64, kernel_size=7, stride=2, padding=3, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
diff --git a/train.py b/train.py
index a81f97abcd5465efe6a01fb3326991f674fa8262..46e5bff84d502a04157c00f1fd29467bf9afe58e 100644
--- a/train.py
+++ b/train.py
@@ -30,22 +30,22 @@ if opt.separated:
signals_train,labels_train,signals_eval,labels_eval = dataloader.loaddataset(opt)
label_cnt,label_cnt_per,label_num = statistics.label_statistics(labels_train)
util.writelog('label statistics: '+str(label_cnt),opt,True)
- opt = options.get_auto_options(opt, label_cnt_per, label_num, signals_train.shape)
+ opt = options.get_auto_options(opt, label_cnt_per, label_num, signals_train)
train_sequences= transformer.k_fold_generator(len(labels_train),opt.k_fold,opt.separated)
eval_sequences= transformer.k_fold_generator(len(labels_eval),opt.k_fold,opt.separated)
else:
signals,labels = dataloader.loaddataset(opt)
label_cnt,label_cnt_per,label_num = statistics.label_statistics(labels)
util.writelog('label statistics: '+str(label_cnt),opt,True)
- opt = options.get_auto_options(opt, label_cnt_per, label_num, signals.shape)
+ opt = options.get_auto_options(opt, label_cnt_per, label_num, signals)
train_sequences,eval_sequences = transformer.k_fold_generator(len(labels),opt.k_fold)
t2 = time.time()
-print('load data cost time: %.2f'% (t2-t1),'s')
+print('Cost time: %.2f'% (t2-t1),'s')
core = core.Core(opt)
core.network_init(printflag=True)
-print('begin to train ...')
+print('Begin to train ...')
fold_final_confusion_mat = np.zeros((opt.label,opt.label), dtype=int)
for fold in range(opt.k_fold):
if opt.k_fold != 1:util.writelog('------------------------------ k-fold:'+str(fold+1)+' ------------------------------',opt,True)
@@ -69,7 +69,7 @@ for fold in range(opt.k_fold):
#save result
if opt.model_name != 'autoencoder':
- pos = core.plot_result['eval'].index(min(core.plot_result['eval']))-1
+ pos = core.plot_result['F1'].index(max(core.plot_result['F1']))
final_confusion_mat = core.confusion_mats[pos]
if opt.k_fold==1:
statistics.statistics(final_confusion_mat, opt, 'final', 'final_eval')
diff --git a/util/array_operation.py b/util/array_operation.py
index 412976df6f4e3f8aa0dd445d21bd65f17e867a58..5156f72ca024cef681c3b577d5e8a02483e06152 100644
--- a/util/array_operation.py
+++ b/util/array_operation.py
@@ -20,7 +20,7 @@ def pad(data, padding, mode = 'zero'):
pad_data = data[:padding-repeat_num*len(data)]
return np.append(out_data, pad_data)
-def normliaze(data, mode = 'norm', sigma = 0, dtype=np.float64, truncated = 2):
+def normliaze(data, mode = 'norm', sigma = 0, dtype=np.float32, truncated = 2):
'''
mode: norm | std | maxmin | 5_95
dtype : np.float64,np.float16...
diff --git a/util/dataloader.py b/util/dataloader.py
index 524e6af53079e7cce7d6a0acf294457803b15e84..b9b7cbda6b7520e0e5f0eace25e91443879fa184 100644
--- a/util/dataloader.py
+++ b/util/dataloader.py
@@ -6,6 +6,7 @@ import scipy.io as sio
import numpy as np
from . import dsp,transformer,statistics
+from . import array_operation as arr
def del_labels(signals,labels,dels):
@@ -92,15 +93,27 @@ def balance_label(signals,labels):
#load all data in datasets
def loaddataset(opt,shuffle = False):
-
+ print('Loading dataset...')
if opt.separated:
signals_train = np.load(opt.dataset_dir+'/signals_train.npy')
labels_train = np.load(opt.dataset_dir+'/labels_train.npy')
signals_eval = np.load(opt.dataset_dir+'/signals_eval.npy')
labels_eval = np.load(opt.dataset_dir+'/labels_eval.npy')
+ if opt.normliaze != 'None':
+ for i in range(signals_train.shape[0]):
+ for j in range(signals_train.shape[1]):
+ signals_train[i][j] = arr.normliaze(signals_train[i][j], mode = opt.normliaze, truncated=5)
+ for i in range(signals_eval.shape[0]):
+ for j in range(signals_eval.shape[1]):
+ signals_eval[i][j] = arr.normliaze(signals_eval[i][j], mode = opt.normliaze, truncated=5)
else:
signals = np.load(opt.dataset_dir+'/signals.npy')
labels = np.load(opt.dataset_dir+'/labels.npy')
+ if opt.normliaze != 'None':
+ for i in range(signals.shape[0]):
+ for j in range(signals.shape[1]):
+ signals[i][j] = arr.normliaze(signals[i][j], mode = opt.normliaze, truncated=5)
+
if not opt.no_shuffle:
transformer.shuffledata(signals,labels)
diff --git a/util/dsp.py b/util/dsp.py
index 15bec69b0f597455d3271f2e1bd1946341d7014b..3fff35f197ec2d73f454b779a39f12a2d3539b02 100644
--- a/util/dsp.py
+++ b/util/dsp.py
@@ -7,7 +7,7 @@ def sin(f,fs,time):
return np.sin(x)
def downsample(signal,fs1=0,fs2=0,alpha=0,mod = 'just_down'):
- if alpha ==0:
+ if alpha == 0:
alpha = int(fs1/fs2)
if mod == 'just_down':
return signal[::alpha]
@@ -74,8 +74,10 @@ def energy(signal,kernel_size,stride,padding = 0):
energy[i] = rms(signal[i*stride:i*stride+kernel_size])
return energy
-def signal2spectrum(data,window_size,stride,log = True):
+def signal2spectrum(data,window_size, stride, n_downsample=1, log = True, log_alpha = 0.1):
# window : ('tukey',0.5) hann
+ if n_downsample != 1:
+ data = downsample(data,alpha=n_downsample)
zxx = scipy.signal.stft(data, window='hann', nperseg=window_size,noverlap=window_size-stride)[2]
spectrum = np.abs(zxx)
@@ -83,11 +85,25 @@ def signal2spectrum(data,window_size,stride,log = True):
if log:
spectrum = np.log1p(spectrum)
h = window_size//2+1
- tmp = np.linspace(0, h-1,num=h,dtype=np.int64)
- index = np.log1p(tmp)*(h/np.log1p(h))
+ x = np.linspace(h*log_alpha, h-1,num=h+1,dtype=np.int64)
+ index = (np.log1p(x)-np.log1p(h*log_alpha))/(np.log1p(h)-np.log1p(h*log_alpha))*h
+
spectrum_new = np.zeros_like(spectrum)
- for i in range(h-1):
+ for i in range(h):
spectrum_new[int(index[i]):int(index[i+1])] = spectrum[i]
spectrum = spectrum_new
+ spectrum = (spectrum-0.05)/0.25
+
+ # spectrum = np.log1p(spectrum)
+ # h = window_size//2+1
+ # tmp = np.linspace(0, h-1,num=h,dtype=np.int64)
+ # index = np.log2(tmp+1)*(h/np.log2(h+1))
+ # spectrum_new = np.zeros_like(spectrum)
+ # for i in range(h-1):
+ # spectrum_new[int(index[i]):int(index[i+1])] = spectrum[i]
+ # spectrum = spectrum_new
+ # spectrum = (spectrum-0.05)/0.25
+ else:
+ spectrum = (spectrum-0.02)/0.05
return spectrum
\ No newline at end of file
diff --git a/util/options.py b/util/options.py
index 59c84af7d9955915bee1f1d6a4ba7657052976d6..a0513435fac4160b3d352144ed35742ed5a796a5 100644
--- a/util/options.py
+++ b/util/options.py
@@ -2,7 +2,7 @@ import argparse
import os
import time
import numpy as np
-from . import util,dsp
+from . import util,dsp,plot
class Options():
def __init__(self):
@@ -18,20 +18,20 @@ class Options():
self.parser.add_argument('--loadsize', type=str, default='auto', help='load data in this size')
self.parser.add_argument('--finesize', type=str, default='auto', help='crop your data into this size')
self.parser.add_argument('--label_name', type=str, default='auto',help='name of labels,example:"a,b,c,d,e,f"')
- self.parser.add_argument('--normliaze', type=str, default='5_95', help='mode of normliaze, 5_95 | maxmin | None')
# ------------------------Dataset------------------------
self.parser.add_argument('--dataset_dir', type=str, default='./datasets/simple_test',help='your dataset path')
self.parser.add_argument('--save_dir', type=str, default='./checkpoints/',help='save checkpoints')
self.parser.add_argument('--separated', action='store_true', help='if specified,for preload data, if input, load separated train and test datasets')
self.parser.add_argument('--no_shuffle', action='store_true', help='if specified, do not shuffle data when load(use to evaluate individual differences)')
- self.parser.add_argument('--load_thread', type=int, default=8,help='how many threads when load data')
+ self.parser.add_argument('--load_thread', type=int, default=8,help='how many threads when load data')
+ self.parser.add_argument('--normliaze', type=str, default='5_95', help='mode of normliaze, 5_95 | maxmin | None')
# ------------------------Network------------------------
"""Available Network
1d: lstm, cnn_1d, resnet18_1d, resnet34_1d, multi_scale_resnet_1d,
micro_multi_scale_resnet_1d,autoencoder
- 2d: dfcnn, multi_scale_resnet, resnet18, resnet50, resnet101,
+ 2d: mobilenet, dfcnn, multi_scale_resnet, resnet18, resnet50, resnet101,
densenet121, densenet201, squeezenet
"""
self.parser.add_argument('--model_name', type=str, default='micro_multi_scale_resnet_1d',help='Choose model lstm...')
@@ -42,9 +42,13 @@ class Options():
# For autoecoder
self.parser.add_argument('--feature', type=int, default=3, help='number of encoder features')
# For 2d network(stft spectrum)
+ # Please cheek ./save_dir/spectrum_eg.jpg to change the following parameters
self.parser.add_argument('--stft_size', type=int, default=512, help='length of each fft segment')
self.parser.add_argument('--stft_stride', type=int, default=128, help='stride of each fft segment')
+ self.parser.add_argument('--stft_n_downsample', type=int, default=1, help='downsample befor stft')
self.parser.add_argument('--stft_no_log', action='store_true', help='if specified, do not log1p spectrum')
+ self.parser.add_argument('--stft_shape', type=str, default='auto', help='shape of stft. It depend on \
+ stft_size,stft_stride,stft_n_downsample. Do not input this parameter.')
# ------------------------Training Matters------------------------
self.parser.add_argument('--pretrained', type=str, default='',help='pretrained model path. If not specified, fo not use pretrained model')
@@ -58,8 +62,6 @@ class Options():
self.parser.add_argument('--mergelabel', type=str, default='None',
help='merge some labels to one label and give the result, example:"[[0,1,4],[2,3,5]]" -> label(0,1,4) regard as 0,label(2,3,5) regard as 1')
self.parser.add_argument('--mergelabel_name', type=str, default='None',help='name of labels,example:"a,b,c,d,e,f"')
- self.parser.add_argument('--plotfreq', type=int, default=100,help='frequency of plotting results')
-
self.initialized = True
@@ -87,7 +89,7 @@ class Options():
'multi_scale_resnet_1d','micro_multi_scale_resnet_1d','autoencoder']:
self.opt.model_type = '1d'
elif self.opt.model_name in ['dfcnn', 'multi_scale_resnet', 'resnet18', 'resnet50',
- 'resnet101','densenet121', 'densenet201', 'squeezenet']:
+ 'resnet101','densenet121', 'densenet201', 'squeezenet', 'mobilenet']:
self.opt.model_type = '2d'
else:
print('\033[1;31m'+'Error: do not support this network '+self.opt.model_name+'\033[0m')
@@ -122,8 +124,9 @@ class Options():
return self.opt
-def get_auto_options(opt,label_cnt_per,label_num,shape):
+def get_auto_options(opt,label_cnt_per,label_num,signals):
+ shape = signals.shape
if opt.label =='auto':
opt.label = label_num
if opt.input_nc =='auto':
@@ -158,8 +161,16 @@ def get_auto_options(opt,label_cnt_per,label_num,shape):
# check stft spectrum
if opt.model_type =='2d':
- h, w = opt.stft_size//2+1, opt.loadsize//opt.stft_stride
- print('Shape of stft spectrum h,w:',(h,w))
+ spectrums = []
+ data = signals[np.random.randint(0,shape[0]-1)]
+ for i in range(shape[1]):
+ spectrums.append(dsp.signal2spectrum(data[i],opt.stft_size, opt.stft_stride, opt.stft_n_downsample, not opt.stft_no_log))
+ plot.draw_spectrums(spectrums,opt)
+ opt.stft_shape = spectrums[0].shape
+ h,w = opt.stft_shape
+ print('Shape of stft spectrum h,w:',opt.stft_shape)
+ print('\033[1;37m'+'Please cheek ./save_dir/spectrum_eg.jpg to change parameters'+'\033[0m')
+
if h<64 or w<64:
print('\033[1;33m'+'Warning: spectrum is too small'+'\033[0m')
if h>512 or w>512:
diff --git a/util/plot.py b/util/plot.py
index 84ec1234d31e19bcbde277b30876141bcc3f62ce..b12a51a13bb61f257ec606ca710a29d0e8633e9e 100644
--- a/util/plot.py
+++ b/util/plot.py
@@ -247,9 +247,15 @@ def showscatter3d(data):
plt.show()
-def draw_spectrum(spectrum,opt):
- plt.imshow(spectrum)
- plt.savefig(os.path.join(opt.save_dir,'spectrum_eg.png'))
+def draw_spectrums(spectrums,opt):
+ if len(spectrums) > 1:
+ plt.subplots(figsize=(6.4*2,4.8*2))
+ for i in range(len(spectrums)):
+ plt.subplot(len(spectrums)//2+1,2,i+1)
+ plt.imshow(spectrums[i])
+ else:
+ plt.imshow(spectrums[0])
+ plt.savefig(os.path.join(opt.save_dir,'spectrum_eg.jpg'))
plt.close('all')
diff --git a/util/transformer.py b/util/transformer.py
index d907e2af8eccc9f4dade2484a11a4a11a4e4ac66..90c15dd23ea0bd78e4b9790a668f6796cdcb73cd 100644
--- a/util/transformer.py
+++ b/util/transformer.py
@@ -77,15 +77,15 @@ def random_transform_1d(data,finesize,test_flag):
# result = result + (noise-0.5)*0.01
return result
-def random_transform_2d(img,finesize = (224,122),test_flag = True):
+def random_transform_2d(img,finesize = (224,244),test_flag = True):
h,w = img.shape[:2]
if test_flag:
- h_move = 2
+ h_move = int((h-finesize[0])*0.5)
w_move = int((w-finesize[1])*0.5)
result = img[h_move:h_move+finesize[0],w_move:w_move+finesize[1]]
else:
#random crop
- h_move = int(10*random.random()) #do not loss low freq signal infos
+ h_move = int((h-finesize[0])*random.random())
w_move = int((w-finesize[1])*random.random())
result = img[h_move:h_move+finesize[0],w_move:w_move+finesize[1]]
#random flip
@@ -99,24 +99,16 @@ def ToInputShape(data,opt,test_flag = False):
#data = data.astype(np.float32)
if opt.model_type == '1d':
- if opt.normliaze != 'None':
- for i in range(opt.batchsize):
- for j in range(opt.input_nc):
- data[i][j] = arr.normliaze(data[i][j],mode = opt.normliaze)
result = random_transform_1d(data, opt.finesize, test_flag=test_flag)
elif opt.model_type == '2d':
result = []
+ h,w = opt.stft_shape
for i in range(opt.batchsize):
for j in range(opt.input_nc):
- spectrum = dsp.signal2spectrum(data[i][j],opt.stft_size,opt.stft_stride, not opt.stft_no_log)
- #spectrum = arr.normliaze(spectrum, mode = opt.normliaze)
- spectrum = (spectrum-2)/5
- # print(spectrum.shape)
- #spectrum = random_transform_2d(spectrum,(224,122),test_flag=test_flag)
+ spectrum = dsp.signal2spectrum(data[i][j],opt.stft_size,opt.stft_stride, opt.stft_n_downsample, not opt.stft_no_log)
+ spectrum = random_transform_2d(spectrum,(h,int(w*0.9)),test_flag=test_flag)
result.append(spectrum)
- h,w = spectrum.shape
- result = (np.array(result)).reshape(opt.batchsize,opt.input_nc,h,w)
-
+ result = (np.array(result)).reshape(opt.batchsize,opt.input_nc,h,int(w*0.9))
return result