├── README.md ├── ReadData_2.py ├── data └── 5HP │ ├── 0.mat │ ├── 1.mat │ ├── 2.mat │ ├── 3.mat │ ├── 4.mat │ ├── 5.mat │ ├── 6.mat │ ├── 7.mat │ ├── 8.mat │ └── 9.mat └── model_2_view.py /README.md: -------------------------------------------------------------------------------- 1 | # MDPS 2 | 3 | ## CCF 4 | **ICME belongs to CCF-B.** 5 | 6 | ![image](https://user-images.githubusercontent.com/19371493/189510285-5d88b69f-bb8d-45b3-9870-02c7fbcebb9d.png) 7 | 8 | ## Idea 9 | ![image](https://user-images.githubusercontent.com/19371493/189364274-4fc4b756-13d5-4b0f-8487-4d188bf415a0.png) 10 | 11 | ## Code 12 | [Unofficial] [pytorch] the implementation of "A Rolling Bearing Fault Diagnosis Method Using Multi-Sensor Data and Periodic Sampling." 13 | 14 | [official code](https://github.com/IWantBe/MDPS) ---tensorflow version (Thanks to [Dr. Zheng](https://github.com/IWantBe) for the open source code) 15 | 16 | - ReadData_2.py : Channel fusion and periodic sampling. 17 | - model_2_view.py : the code of training and testing, and it provides functions to evaluate the performance changes under different stripe and sample length. 18 | 19 | ## Cited 20 | ```html 21 | @inproceedings{DBLP:conf/icmcs/Zheng0Z022, 22 | author = {Jianbo Zheng and 23 | Chao Yang and 24 | Fangrong Zheng and 25 | Bin Jiang}, 26 | title = {A Rolling Bearing Fault Diagnosis Method Using Multi-Sensor Data and 27 | Periodic Sampling}, 28 | booktitle = {{IEEE} International Conference on Multimedia and Expo, {ICME} 2022, 29 | Taipei, Taiwan, July 18-22, 2022}, 30 | pages = {1--6}, 31 | publisher = {{IEEE}}, 32 | year = {2022}, 33 | url = {https://doi.org/10.1109/ICME52920.2022.9859658}, 34 | doi = {10.1109/ICME52920.2022.9859658}, 35 | timestamp = {Wed, 31 Aug 2022 11:49:15 +0200}, 36 | biburl = {https://dblp.org/rec/conf/icmcs/Zheng0Z022.bib}, 37 | bibsource = {dblp computer science bibliography, https://dblp.org} 38 | } 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /ReadData_2.py: -------------------------------------------------------------------------------- 1 | from scipy.io import loadmat 2 | import numpy as np 3 | import os 4 | from sklearn import preprocessing # 0-1编码 5 | import torch 6 | from torch.utils import data as da 7 | 8 | # 用训练集标准差标准化训练集以及测试集 9 | def scalar_stand(data_x): 10 | scalar = preprocessing.StandardScaler().fit(data_x) 11 | data_x = scalar.transform(data_x) 12 | return data_x 13 | 14 | 15 | # one-hot编码 16 | # def one_hot(data_y): 17 | # data_y = np.array(data_y).reshape([-1, 1]) 18 | # encoder = preprocessing.OneHotEncoder() 19 | # encoder.fit(data_y) 20 | # data_y = encoder.transform(data_y).toarray() 21 | # data_y = np.asarray(data_y, dtype=np.int32) 22 | # return data_y 23 | 24 | 25 | # 构建文件读取函数capture,返回原始数据和标签数据 26 | def capture(original_path): # 读取mat文件,返回一个属性的字典 27 | filenames = os.listdir(original_path) # 得到负载文件夹下面的10个文件名 28 | Data_DE = {} 29 | Data_FE = {} 30 | for i in filenames: # 遍历10个文件数据 31 | # 文件路径 32 | file_path = os.path.join(original_path, i) # 选定一个数据文件的路径 33 | file = loadmat(file_path) # 字典 34 | file_keys = file.keys() # 字典的所有key值 35 | for key in file_keys: 36 | if 'DE' in key: # 只获取DE 37 | Data_DE[i] = file[key].ravel() # 将数据拉成一维数组 38 | if 'FE' in key: # 只获取DE 39 | Data_FE[i] = file[key].ravel() # 将数据拉成一维数组 40 | return Data_DE, Data_FE 41 | 42 | 43 | # 划分训练样点集和测试样点集 44 | def spilt(data, rate): # [[N1],[N2],...,[N10]] 45 | keys = data.keys() # 10个文件名 46 | tra_data = [] 47 | te_data = [] 48 | val_data = [] 49 | for i in keys: # 遍历所有文件夹 50 | slice_data = data[i] # 选取1个文件中的数据 51 | # slice_data = scalar_stand(slice_data) 52 | all_length = len(slice_data) # 文件中的数据长度 53 | # print('数据总数为', all_length) 54 | tra_data.append(slice_data[0:int(all_length * rate[0])]) 55 | # print("训练样本点数", len(tra_data)) 56 | val_data.append((slice_data[int(all_length * rate[0]):int(all_length * (rate[0]+rate[1]))])) 57 | te_data.append(slice_data[int(all_length * (rate[0]+rate[1])):]) 58 | # print("测试样本点数", len(te_data)) 59 | return tra_data, val_data, te_data 60 | 61 | 62 | def sampling(data_DE, data_FE, step, sample_len): 63 | sample_DE = [] 64 | sample_FE = [] 65 | label = [] 66 | lab = 0 67 | for i in range(len(data_DE)): # 遍历10个文件 68 | all_length = len(data_DE[i]) # 文件中的数据长度 69 | # print('采样的训练数据总数为', all_length) 70 | number_sample = int((all_length - sample_len)/step + 1) # 样本数 71 | # print("number=", number_sample) 72 | for j in range(number_sample): # 逐个采样 73 | sample_DE.append(data_DE[i][j * step: j * step + sample_len]) 74 | sample_FE.append(data_FE[i][j * step: j * step + sample_len]) 75 | label.append(lab) 76 | j += 1 77 | lab = lab + 1 78 | sample = np.stack((np.array(sample_DE), np.array(sample_FE)), axis=2) 79 | return sample, label 80 | 81 | 82 | def get_data(path, rate, step, sample_len): 83 | data_DE, data_FE = capture(path) # 读取数据 84 | train_data_DE, val_data_DE, test_data_DE = spilt(data_DE, rate) # 列表[N1,N2,N10] 85 | train_data_FE, val_data_FE, test_data_FE = spilt(data_FE, rate) 86 | x_train, y_train = sampling(train_data_DE, train_data_FE, step, sample_len) 87 | # y_train = F.one_hot(torch.Tensor(y_train).long(), num_classes=10) 88 | x_validate, y_validate = sampling(val_data_DE, val_data_FE, step, sample_len) 89 | x_test, y_test = sampling(test_data_DE, test_data_FE, step, sample_len) 90 | return x_train, y_train, x_validate, y_validate, x_test, y_test 91 | 92 | class Dataset(da.Dataset): 93 | def __init__(self, X, y): 94 | self.Data = X 95 | self.Label = y 96 | def __getitem__(self, index): 97 | txt = self.Data[index] 98 | label = self.Label[index] 99 | return txt, label 100 | def __len__(self): 101 | return len(self.Data) 102 | 103 | if __name__ == "__main__": 104 | path = r'data\5HP' 105 | rate = [0.7, 0.15, 0.15] 106 | step = 210 107 | sample_len = 420 108 | x_train, y_train, x_validate, y_validate, x_test, y_test = get_data(path, rate, step, sample_len) 109 | print(x_train.shape) # (5267, 420, 2) 110 | print(x_validate.shape) # (1117, 420, 2) 111 | print(x_test.shape) # (1117, 420, 2) 112 | # sample = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 按照样本数进行切片得到每一片的表述(400,2) 113 | # sample = sample.shuffle(1000).batch(10) # 打乱分批量(10,400,2) 114 | # sample_test = tf.data.Dataset.from_tensor_slices((x_test, y_test)) 115 | # sample_test = sample_test.shuffle(1000).batch(10) # 打乱分批量(10,400,2) 116 | Train = Dataset(torch.from_numpy(x_train).permute(0, 2, 1), y_train) 117 | Test = Dataset(torch.from_numpy(x_test).permute(0, 2, 1), y_test) 118 | train_loader = da.DataLoader(Train, batch_size=10, shuffle=True) 119 | test_loader = da.DataLoader(Test, batch_size=10, shuffle=False) -------------------------------------------------------------------------------- /data/5HP/0.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/0.mat -------------------------------------------------------------------------------- /data/5HP/1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/1.mat -------------------------------------------------------------------------------- /data/5HP/2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/2.mat -------------------------------------------------------------------------------- /data/5HP/3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/3.mat -------------------------------------------------------------------------------- /data/5HP/4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/4.mat -------------------------------------------------------------------------------- /data/5HP/5.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/5.mat -------------------------------------------------------------------------------- /data/5HP/6.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/6.mat -------------------------------------------------------------------------------- /data/5HP/7.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/7.mat -------------------------------------------------------------------------------- /data/5HP/8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/8.mat -------------------------------------------------------------------------------- /data/5HP/9.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liguge/MDPS_pytorch/3f6828d9ed8b10c782385dd0d5f3ac6e27e44212/data/5HP/9.mat -------------------------------------------------------------------------------- /model_2_view.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import ReadData_2 as RD 3 | import torch 4 | import torch.nn as nn 5 | from torch.utils import data as da 6 | from timm.loss import LabelSmoothingCrossEntropy 7 | import argparse 8 | args = None 9 | 10 | def parse_args(): 11 | parser = argparse.ArgumentParser(description='Train') 12 | parser.add_argument('--data_dir', type=str, default= "data\\5HP", help='') 13 | parser.add_argument("--pretrained", type=bool, default=True, help='') 14 | parser.add_argument('--batch_size', type=int, default=256, help='batchsize of the training process') 15 | parser.add_argument('--step_len', type=list, default=range(210, 430, 10), help='') 16 | parser.add_argument('--sample_len', type=int, default=420, help='') 17 | parser.add_argument('--rate', type=list, default=[0.7, 0.15, 0.15], help='') 18 | parser.add_argument('--acces', type=list, default=[], help='initialization list') 19 | parser.add_argument('--epochs', type=int, default=80, help='max number of epoch') 20 | parser.add_argument('--losses', type=list, default=[], help='initialization list') 21 | args = parser.parse_args() 22 | return args 23 | 24 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 25 | 26 | class Dataset(da.Dataset): 27 | def __init__(self, X, y): 28 | self.Data = X 29 | self.Label = y 30 | def __getitem__(self, index): 31 | txt = self.Data[index] 32 | label = self.Label[index] 33 | return txt, label 34 | def __len__(self): 35 | return len(self.Data) 36 | 37 | # STEP1 加载数据 38 | def load_data(args, step): 39 | # path = r'data\5HP' 40 | # path = args.data_dir 41 | # rate = args.rate 42 | x_train, y_train, x_validate, y_validate, x_test, y_test = RD.get_data(args.data_dir, args.rate, step, args.sample_len) 43 | # 切片 44 | # sample = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 按照样本数进行切片得到每一片的表述(2048+10,1) 45 | # sample = sample.shuffle(1000).batch(10) # 打乱分批量(10,400,2) 46 | # sample_validate = tf.data.Dataset.from_tensor_slices((x_validate, y_validate)) 47 | # sample_validate = sample_validate.shuffle(1000).batch(10) # 打乱分批量(10,400,2) 48 | # sample_test = tf.data.Dataset.from_tensor_slices((x_test, y_test)) 49 | # sample_test = sample_test.shuffle(1000).batch(10) # 打乱分批量(10,400,2) 50 | Train = Dataset(torch.from_numpy(x_train).permute(0, 2, 1), y_train) 51 | Validate = Dataset(torch.from_numpy(x_validate).permute(0, 2, 1), y_validate) 52 | Test = Dataset(torch.from_numpy(x_test).permute(0, 2, 1), y_test) 53 | train_loader = da.DataLoader(Train, batch_size=args.batch_size, shuffle=True) 54 | validate_loader = da.DataLoader(Validate, batch_size=args.batch_size, shuffle=True) 55 | test_loader = da.DataLoader(Test, batch_size=args.batch_size, shuffle=False) 56 | return train_loader, validate_loader, test_loader 57 | 58 | 59 | # STEP2 设计网络结构,建立网络容器 60 | # def create_model(): 61 | # Con_net = keras.Sequential([ # 网络容器 62 | # layers.Conv1D(filters=32, kernel_size=20, strides=1, padding='same', activation='relu'), # 添加卷积层 63 | # layers.BatchNormalization(), # 添加正则化层 64 | # layers.MaxPooling1D(pool_size=2, strides=2, padding='same'), # 池化层 65 | # layers.Conv1D(filters=32, kernel_size=20, strides=1, padding='same', activation='relu'), # 添加卷积层 66 | # layers.BatchNormalization(), # 添加正则化层 67 | # layers.MaxPooling1D(pool_size=2, strides=2, padding='same'), # 池化层 68 | # layers.Flatten(), # 打平层,方便全连接层使用 69 | # layers.Dense(100, activation='relu'), # 全连接层,120个节点 70 | # layers.Dense(10, activation='softmax'), # 全连接层,10个类别节点 71 | # ]) 72 | # return Con_net 73 | class Con_net(nn.Module): 74 | def __init__(self): 75 | super(Con_net, self).__init__() 76 | self.p1_1 = nn.Sequential(nn.Conv1d(2, 32, kernel_size=20, stride=1, padding='same'), 77 | nn.BatchNorm1d(32), 78 | nn.ReLU(inplace=True)) 79 | self.p1_2 = nn.MaxPool1d(2, 2) 80 | self.p2_1 = nn.Sequential(nn.Conv1d(32, 32, kernel_size=20, stride=1, padding='same'), 81 | nn.BatchNorm1d(32), 82 | nn.ReLU(inplace=True)) 83 | self.p2_2 = nn.MaxPool1d(2, 2) 84 | self.p3_1 = nn.Sequential(nn.Linear(32*105, 100), #需要根据输出修改前置神经元个数 85 | nn.ReLU(inplace=True)) #全连接层之后还需要加激活函数 86 | self.p3_2 = nn.Sequential(nn.Linear(100, 10)) 87 | 88 | def forward(self, x): 89 | x = self.p1_2(self.p1_1(x)) 90 | x = self.p2_2(self.p2_1(x)) 91 | x = x.reshape(-1, x.size()[1]*x.size()[2]) 92 | x = self.p3_2(self.p3_1(x)) 93 | return x 94 | 95 | model = Con_net().to(device) 96 | 97 | def train(args, train_loader, validate_loader, test_loader): 98 | res = [] 99 | optimizer = torch.optim.Adam(model.parameters(), lr=1e-4) 100 | criterion = LabelSmoothingCrossEntropy() 101 | train_loss = 0.0 102 | train_acc = 0.0 103 | model.train() 104 | for epoch in range(args.epochs): 105 | for step, (img, label) in enumerate(train_loader): 106 | img = img.float() 107 | img = img.to(device) 108 | label = label.to(device) 109 | label = label.long() 110 | out = model(img) 111 | out = torch.squeeze(out).float() 112 | loss = criterion(out, label) 113 | optimizer.zero_grad() 114 | loss.backward() 115 | optimizer.step() 116 | train_loss += loss.item() 117 | _, pred = out.max(1) 118 | num_correct = (pred == label).sum().item() 119 | acc = num_correct / img.shape[0] 120 | train_acc += acc 121 | if step % 37 == 0: 122 | print(epoch, step, 'loss:', float(loss)) 123 | # print(epoch, step, 'loss:', float(loss)) 124 | res.append(test(test_loader)) 125 | result.append(res) 126 | return test(test_loader) 127 | # torch.save(model.state_dict(), './cnn_save_weights_400.pt') 128 | 129 | # def train(sample1, sample1_validate, sample1_test, sample_len): 130 | # res = [] 131 | # Con_net = create_model() # 建立网络模型 132 | # Con_net.build(input_shape=(10, sample_len, 2)) # 构建一个卷积网络,输入的尺寸 ---------------------- 133 | # optimizer = optimizers.Adam(lr=1e-4) # 设置优化器 134 | # variables = Con_net.trainable_variables 135 | # for epoch in range(epochs): # 外循环,遍历多少次训练数据集 136 | # for step, (x, y) in enumerate(sample1): # 遍历一次训练集的所有样例 137 | # with tf.GradientTape() as tape: # 构建梯度环境 # [b, 32, 32, 3] => [b, 1, 1, 512] 138 | # out = Con_net(x) # flatten, => [b, 512] 139 | # loss = tf.losses.categorical_crossentropy(y, out) # compute loss 140 | # loss = tf.reduce_mean(loss) # 求损失的平均值 141 | # grads = tape.gradient(loss, variables) 142 | # optimizer.apply_gradients(zip(grads, variables)) 143 | # if step % 1000 == 0: 144 | # print(epoch, step, 'loss:', float(loss)) 145 | # # print("验证集正确率") 146 | # # test(Con_net, sample1_validate) 147 | # # print("测试集正确率") 148 | # res.append(test(Con_net, sample1_test)) 149 | # result.append(res) 150 | # # Con_net.save_weights('./cnn_save_weights_400') 151 | 152 | def test(sample_data): 153 | 154 | test_acc = 0. 155 | model.eval() 156 | for img, label in sample_data: 157 | # torch.load('./cnn_save_weights_400.pt') 158 | img = img.float() 159 | img = img.to(device) 160 | label = label.to(device) 161 | label = label.long() 162 | out = model(img) 163 | out = torch.squeeze(out).float() 164 | _, pred = out.max(1) 165 | num_correct = (pred == label).sum().item() 166 | acc = num_correct / img.shape[0] 167 | test_acc += acc 168 | acc = test_acc / len(sample_data) 169 | # print('acc:', acc) 170 | return acc 171 | # 172 | # 173 | # def test(Con_net, sample_data): 174 | # total_num = 0 175 | # total_correct = 0 176 | # for x, y in sample_data: 177 | # # Con_net = create_model() # 建立网络模型 178 | # # Con_net.load_weights('./cnn_save_weights_400') 179 | # out = Con_net(x) # 前向计算 180 | # predict = tf.argmax(out, axis=-1) # axis=-1, 倒数第一维, 返回每行的最大值坐标 181 | # # print("predict", predict) 182 | # y = tf.cast(y, tf.int64) 183 | # # print("y", y) 184 | # m = predict == y 185 | # m = tf.cast(m, dtype=tf.int64) # tensor张量类型 186 | # total_correct += int(tf.reduce_sum(m)) 187 | # total_num += x.shape[0] 188 | # if total_num < total_correct: 189 | # print("error---------------------------") 190 | # print("正确",total_correct,"总数",total_num) 191 | # acc = total_correct / total_num 192 | # # print('acc:', acc) 193 | # return acc 194 | 195 | def run_step(args): # epoch=10 196 | # step_len = list(range(210, 430, 10)) 197 | #step_len = [420] 198 | # step_len = [210] 199 | for i in list(args.step_len): 200 | sample1, sample1_validate, sample1_test = load_data(args, step=i) 201 | acc = train(args, sample1, sample1_validate, sample1_test) 202 | print(acc) 203 | 204 | 205 | # def run_sample(): 206 | # sample_len = list(range(1,7)) 207 | # # sample_len = [1] 208 | # for i in sample_len: 209 | # sample1, sample1_validate, sample1_test = load_data(step=210, sample_len=420*i) 210 | # train(sample1, sample1_validate, sample1_test, sample_len=420*i) 211 | 212 | 213 | # 当epoch=10时,随着步长的变化,实验结果的变化 214 | if __name__ == '__main__': 215 | args = parse_args() 216 | result = [] 217 | run_step(args) 218 | # run_sample() 219 | print(result) 220 | 221 | 222 | --------------------------------------------------------------------------------