├── .gitattributes ├── CNN_feature_extracting ├── feature_extracting.py ├── view1_CNNmodel.py ├── view2_CNNmodel.py └── view3_CNNmodel.py ├── README.md ├── data └── raw_data │ ├── data1.mat │ └── data2.mat ├── mult_TSK_FS ├── auto_expt_mul_TSK.m ├── confusion_matrix.m ├── expt_mul_TSK.m ├── fromXtoZ.m ├── lab2vec.m ├── preproc.m ├── test_TSK_FS.m ├── test_mul_TSK.m ├── train_TSK_FS.m ├── train_mul_TSK.m └── vec2lab.m └── preprocessing ├── domain_transform.m ├── load_data.m └── preprocessing_data.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /CNN_feature_extracting/feature_extracting.py: -------------------------------------------------------------------------------- 1 | # 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | # 3 | # construction three deep feature extraction network 4 | # Construction of deep multi-view features 5 | 6 | import view1_CNNmodel 7 | import view2_CNNmodel 8 | import view3_CNNmodel 9 | import scipy.io as sio 10 | import numpy as np 11 | import h5py 12 | 13 | 14 | def data_preprocess(file_name): 15 | X_1 = h5py.File(file_name)['X_1'] 16 | X_1 = np.transpose(X_1) 17 | 18 | X_2 = h5py.File(file_name)['X_2'] 19 | X_2 = np.transpose(X_2) 20 | 21 | X_3 = h5py.File(file_name)['X_3'] 22 | X_3 = np.transpose(X_3) 23 | 24 | Y = h5py.File(file_name)['Y'] 25 | Y = np.transpose(Y) 26 | 27 | return X_1, X_2, X_3, Y 28 | 29 | 30 | def split(X_1, X_2, X_3, Y, k): 31 | fold_num = 5 32 | tr_X_1 = np.empty(shape=[0, X_1.shape[1]], dtype='float32') 33 | tr_X_2 = np.empty(shape=[0, X_2.shape[1]], dtype='float32') 34 | tr_X_3 = np.empty(shape=[0, X_3.shape[1]], dtype='float32') 35 | tr_Y = np.empty(shape=[0, Y.shape[1]]) 36 | 37 | for fold in range(fold_num): 38 | if fold+1 == k: 39 | te_X_1 = X_1[fold:: fold_num, :] 40 | te_X_2 = X_2[fold:: fold_num, :] 41 | te_X_3 = X_3[fold:: fold_num, :] 42 | te_Y = Y[fold:: fold_num, :] 43 | else: 44 | tr_X_1 = np.append(tr_X_1, X_1[fold:-1:fold_num, :], axis=0) 45 | tr_X_2 = np.append(tr_X_2, X_2[fold:-1:fold_num, :], axis=0) 46 | tr_X_3 = np.append(tr_X_3, X_3[fold:-1:fold_num, :], axis=0) 47 | tr_Y = np.append(tr_Y, Y[fold:-1:fold_num, :], axis=0) 48 | 49 | return te_X_1, te_X_2, te_X_3, te_Y, tr_X_1, tr_X_2, tr_X_3, tr_Y 50 | 51 | 52 | steps_1 = 3000 53 | steps_2 = 2000 54 | steps_3 = 5000 55 | for i in range(7, 25): 56 | #modeldir_name = 'model' 57 | #if os.path.isdir(modeldir_name): 58 | #shutil.rmtree(modeldir_name) 59 | for k in range(1, 6): 60 | print("\ndata_set:{}".format(i)) 61 | print("loop:{}".format(k)) 62 | 63 | file_name = '../data/domain_feature/train_data' + str(i) + '.mat' 64 | X_1, X_2, X_3, Y = data_preprocess(file_name) 65 | 66 | te_X_1, te_X_2, te_X_3, te_Y, tr_X_1, tr_X_2, tr_X_3, tr_Y = split(X_1, X_2, X_3, Y, k) 67 | 68 | print("\ntrain view_1 CNNmodel") 69 | view1_CNNmodel.extracting_feature('train', tr_X_1, tr_Y, steps_1, i, k) 70 | print("\ntrain view_2 CNNmodel") 71 | view2_CNNmodel.extracting_feature('train', tr_X_2, tr_Y, steps_2, i, k) 72 | print("\ntrain view_3 CNNmodel") 73 | view3_CNNmodel.extracting_feature('train', tr_X_3, tr_Y, steps_3, i, k) 74 | 75 | print("\nextracting multi-view feature") 76 | tr_X_1 = view1_CNNmodel.extracting_feature('predict', tr_X_1, tr_Y, steps_1, i, k) 77 | tr_X_2 = view2_CNNmodel.extracting_feature('predict', tr_X_2, tr_Y, steps_2, i, k) 78 | tr_X_3 = view3_CNNmodel.extracting_feature('predict', tr_X_3, tr_Y, steps_3, i, k) 79 | 80 | tr_X_1 = np.array(tr_X_1) 81 | tr_X_2 = np.array(tr_X_2) 82 | tr_X_3 = np.array(tr_X_3) 83 | sio.savemat('../data/feature/fold_' + str(k) + '/data_' + str(i) + '_train', {'tr_X_1':tr_X_1, 84 | 'tr_X_2': tr_X_2, 85 | 'tr_X_3': tr_X_3, 86 | 'tr_Y': tr_Y 87 | }) 88 | 89 | te_X_1 = view1_CNNmodel.extracting_feature('predict', te_X_1, te_Y, steps_1, i, k) 90 | te_X_2 = view2_CNNmodel.extracting_feature('predict', te_X_2, te_Y, steps_2, i, k) 91 | te_X_3 = view3_CNNmodel.extracting_feature('predict', te_X_3, te_Y, steps_3, i, k) 92 | 93 | te_X_1 = np.array(te_X_1) 94 | te_X_2 = np.array(te_X_2) 95 | te_X_3 = np.array(te_X_3) 96 | sio.savemat('../data/feature/fold_' + str(k) + '/data_' + str(i) + '_predict', {'te_X_1': te_X_1, 97 | 'te_X_2': te_X_2, 98 | 'te_X_3': te_X_3, 99 | 'te_Y': te_Y 100 | }) 101 | -------------------------------------------------------------------------------- /CNN_feature_extracting/view1_CNNmodel.py: -------------------------------------------------------------------------------- 1 | # 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | # 3 | # construction the time domain deep feature extraction network 4 | # Calculate the time deep feature 5 | 6 | import tensorflow as tf 7 | 8 | 9 | def extracting_feature(mode, data, labels, steps, i, k): 10 | classifier = tf.estimator.Estimator(model_fn=cnn_model, params={ 11 | 'channels': 23, 12 | 'samples': 256, 13 | 'n_classes': 2, 14 | }, 15 | model_dir="model/loop_" + str(k) + "/data_" + str(i) + "/view1_model") 16 | 17 | if mode == "train": 18 | train_input_fn = tf.estimator.inputs.numpy_input_fn( 19 | x={"x": data}, 20 | y=labels, 21 | batch_size=100, 22 | num_epochs=None, 23 | shuffle=True 24 | ) 25 | tensor_to_log = {"probabilities": "softmax_tensor"} 26 | logging_hook = tf.train.LoggingTensorHook(tensors=tensor_to_log, every_n_iter=50) 27 | classifier.train(input_fn=train_input_fn, steps=steps, hooks=[logging_hook]) 28 | 29 | elif mode == "eval": 30 | eval_input_fn = tf.estimator.inputs.numpy_input_fn( 31 | x={"x": data}, 32 | y=labels, 33 | num_epochs=1, 34 | shuffle=False 35 | ) 36 | eval_result = classifier.evaluate(input_fn=eval_input_fn) 37 | return eval_result 38 | 39 | elif mode == "predict": 40 | predict_input_fn = tf.estimator.inputs.numpy_input_fn( 41 | x={"x": data}, 42 | num_epochs=1, 43 | shuffle=False 44 | ) 45 | predictions = list(classifier.predict(input_fn=predict_input_fn)) 46 | #将特征图作为结果输出; 47 | classes = [p["feature_mapping"] for p in predictions] 48 | return classes 49 | 50 | 51 | def cnn_model(features, labels, mode, params): 52 | #1D cnn模型 53 | #四个卷积层和两个全连接层; 54 | #第一个全连接层输出的1*1024的向量即为特征图; 55 | 56 | X = tf.reshape(features["x"], [-1, params['channels'], params['samples'], 1]) 57 | X_conv1 = tf.layers.conv2d(inputs=X, filters=1, kernel_size=[1, 128], padding='valid', activation=tf.nn.tanh) 58 | X_conv2 = tf.layers.conv2d(inputs=X_conv1, filters=30, kernel_size=[1, 65], padding='valid', activation=tf.nn.tanh) 59 | X_conv3 = tf.layers.conv2d(inputs=X_conv2, filters=20, kernel_size=[4, 33], padding='valid', activation=tf.nn.tanh) 60 | X_conv4 = tf.layers.conv2d(inputs=X_conv3, filters=10, kernel_size=[8, 18], padding='valid', activation=tf.nn.tanh) 61 | X_dense1 = tf.layers.dense(inputs=tf.reshape(X_conv4, [-1, 13*16*10]), units=1024, activation=tf.nn.tanh) 62 | X_dense2 = tf.layers.dense(inputs=X_dense1, units=100, activation=tf.nn.tanh) 63 | logits = tf.layers.dense(inputs=X_dense2, units=params['n_classes'], activation=None) 64 | 65 | predictions = { 66 | "classes": tf.argmax(input=logits, axis=1)[:, tf.newaxis], 67 | "probabilities": tf.nn.softmax(logits, name='softmax_tensor'), 68 | "feature_mapping": X_dense2, 69 | } 70 | 71 | if mode == tf.estimator.ModeKeys.PREDICT: 72 | return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) 73 | 74 | elif mode == tf.estimator.ModeKeys.TRAIN: 75 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 76 | optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) 77 | train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step()) 78 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) 79 | 80 | elif mode == tf.estimator.ModeKeys.EVAL: 81 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 82 | 83 | eval_metric_ops = { 84 | "Accuracy": tf.metrics.accuracy(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 85 | "TP": tf.metrics.true_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 86 | "FN": tf.metrics.false_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 87 | "TN": tf.metrics.true_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 88 | "FP": tf.metrics.false_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 89 | } 90 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops) -------------------------------------------------------------------------------- /CNN_feature_extracting/view2_CNNmodel.py: -------------------------------------------------------------------------------- 1 | # 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | # 3 | # construction the frequency domain deep feature extraction network 4 | # Calculate the frequency deep feature 5 | 6 | import tensorflow as tf 7 | 8 | 9 | def extracting_feature(mode, data, labels, steps, i, k): 10 | classifier = tf.estimator.Estimator(model_fn=cnn_model, params={ 11 | 'channels': 23, 12 | 'samples': 27, 13 | 'n_classes': 2, 14 | }, 15 | model_dir="model/loop_" + str(k) + "/data_" + str(i) + "/view2_model") 16 | 17 | if mode == "train": 18 | train_input_fn = tf.estimator.inputs.numpy_input_fn( 19 | x={"x": data}, 20 | y=labels, 21 | batch_size=100, 22 | num_epochs=None, 23 | shuffle=True 24 | ) 25 | tensor_to_log = {"probabilities": "softmax_tensor"} 26 | logging_hook = tf.train.LoggingTensorHook(tensors=tensor_to_log, every_n_iter=50) 27 | classifier.train(input_fn=train_input_fn, steps=steps, hooks=[logging_hook]) 28 | 29 | elif mode == "eval": 30 | eval_input_fn = tf.estimator.inputs.numpy_input_fn( 31 | x={"x": data}, 32 | y=labels, 33 | num_epochs=1, 34 | shuffle=False 35 | ) 36 | eval_result = classifier.evaluate(input_fn=eval_input_fn) 37 | return eval_result 38 | 39 | elif mode == "predict": 40 | predict_input_fn = tf.estimator.inputs.numpy_input_fn( 41 | x={"x": data}, 42 | num_epochs=1, 43 | shuffle=False 44 | ) 45 | predictions = list(classifier.predict(input_fn=predict_input_fn)) 46 | #将特征图作为结果输出; 47 | classes = [p["feature_mapping"] for p in predictions] 48 | return classes 49 | 50 | 51 | def cnn_model(features, labels, mode, params): 52 | #1D cnn模型 53 | #四个卷积层和两个全连接层; 54 | #第一个全连接层输出的1*1024的向量即为特征图; 55 | 56 | X = tf.reshape(features["x"], [-1, params['channels'], params['samples'], 1]) 57 | X_conv1 = tf.layers.conv2d(inputs=X, filters=20, kernel_size=[4,4], padding='valid', activation=tf.nn.tanh) 58 | X_conv2 = tf.layers.conv2d(inputs=X_conv1, filters=10, kernel_size=[8,8], padding='valid', activation=tf.nn.tanh) 59 | X_dense1 = tf.layers.dense(inputs=tf.reshape(X_conv2, [-1, 13*17*10]), units=512, activation=tf.nn.tanh) 60 | X_dense2 = tf.layers.dense(inputs=X_dense1, units=100, activation=tf.nn.tanh) 61 | logits = tf.layers.dense(inputs=X_dense2, units=params['n_classes'], activation=None) 62 | 63 | predictions = { 64 | "classes": tf.argmax(input=logits, axis=1)[:, tf.newaxis], 65 | "probabilities": tf.nn.softmax(logits, name='softmax_tensor'), 66 | "feature_mapping": X_dense2, 67 | } 68 | 69 | if mode == tf.estimator.ModeKeys.PREDICT: 70 | return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) 71 | 72 | elif mode == tf.estimator.ModeKeys.TRAIN: 73 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 74 | optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) 75 | train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step()) 76 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) 77 | 78 | elif mode == tf.estimator.ModeKeys.EVAL: 79 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 80 | 81 | eval_metric_ops = { 82 | "Accuracy": tf.metrics.accuracy(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 83 | "TP": tf.metrics.true_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 84 | "FN": tf.metrics.false_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 85 | "TN": tf.metrics.true_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 86 | "FP": tf.metrics.false_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 87 | } 88 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops) -------------------------------------------------------------------------------- /CNN_feature_extracting/view3_CNNmodel.py: -------------------------------------------------------------------------------- 1 | # 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | # 3 | # construction the time-frequency domain deep feature extraction network 4 | # Calculate the time-frequency deep feature 5 | 6 | import tensorflow as tf 7 | 8 | 9 | def extracting_feature(mode, data, labels, steps, i, k): 10 | classifier = tf.estimator.Estimator(model_fn=cnn_model, params={ 11 | 'channels': 23, 12 | 'frequency_point': 14, 13 | 'time_point': 256, 14 | 'n_classes': 2, 15 | }, 16 | model_dir="model/loop_" + str(k) + "/data_" + str(i) + "/view3_model") 17 | 18 | if mode == "train": 19 | train_input_fn = tf.estimator.inputs.numpy_input_fn( 20 | x={"x": data}, 21 | y=labels, 22 | batch_size=100, 23 | num_epochs=None, 24 | shuffle=True 25 | ) 26 | tensor_to_log = {"probabilities": "softmax_tensor"} 27 | logging_hook = tf.train.LoggingTensorHook(tensors=tensor_to_log, every_n_iter=50) 28 | classifier.train(input_fn=train_input_fn, steps=steps, hooks=[logging_hook]) 29 | 30 | elif mode == "eval": 31 | eval_input_fn = tf.estimator.inputs.numpy_input_fn( 32 | x={"x": data}, 33 | y=labels, 34 | num_epochs=1, 35 | shuffle=False 36 | ) 37 | eval_result = classifier.evaluate(input_fn=eval_input_fn) 38 | return eval_result 39 | 40 | elif mode == "predict": 41 | predict_input_fn = tf.estimator.inputs.numpy_input_fn( 42 | x={"x": data}, 43 | num_epochs=1, 44 | shuffle=False 45 | ) 46 | predictions = list(classifier.predict(input_fn=predict_input_fn)) 47 | #将特征图作为结果输出; 48 | classes = [p["feature_mapping"] for p in predictions] 49 | return classes 50 | 51 | 52 | def cnn_model(features, labels, mode, params): 53 | #1D cnn模型 54 | #四个卷积层和两个全连接层; 55 | #第一个全连接层输出的1*1024的向量即为特征图; 56 | 57 | X = tf.reshape(features["x"], [-1, params['channels'], params['frequency_point'], params['time_point'], 1]) 58 | X = tf.transpose(X, perm=[0, 3, 1, 2, 4]) 59 | X_conv1 = tf.layers.conv3d(inputs=X, filters=1, kernel_size=[129, 1, 1], padding='valid', activation=tf.nn.tanh) 60 | X_conv2 = tf.layers.conv3d(inputs=X_conv1, filters=30, kernel_size=[65, 4, 4], padding='valid', activation=tf.nn.tanh) 61 | X_conv3 = tf.layers.conv3d(inputs=X_conv2, filters=20, kernel_size=[33, 4, 4], padding='valid', activation=tf.nn.tanh) 62 | X_conv4 = tf.layers.conv3d(inputs=X_conv3, filters=10, kernel_size=[17, 8, 1], padding='valid', activation=tf.nn.tanh) 63 | X_dense1 = tf.layers.dense(inputs=tf.reshape(X_conv4, [-1, 16 * 10 * 8 * 10]), units=2048, activation=tf.nn.tanh) 64 | X_dense2 = tf.layers.dense(inputs=X_dense1, units=1024, activation=tf.nn.tanh) 65 | X_dense3 = tf.layers.dense(inputs=X_dense2, units=100, activation=tf.nn.tanh) 66 | logits = tf.layers.dense(inputs=X_dense3, units=params['n_classes'], activation=None) 67 | 68 | predictions = { 69 | "classes": tf.argmax(input=logits, axis=1)[:, tf.newaxis], 70 | "probabilities": tf.nn.softmax(logits, name='softmax_tensor'), 71 | "feature_mapping": X_dense3, 72 | } 73 | 74 | if mode == tf.estimator.ModeKeys.PREDICT: 75 | return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) 76 | 77 | elif mode == tf.estimator.ModeKeys.TRAIN: 78 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 79 | optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) 80 | train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step()) 81 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) 82 | 83 | elif mode == tf.estimator.ModeKeys.EVAL: 84 | loss = tf.reduce_mean(tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)) 85 | 86 | eval_metric_ops = { 87 | "Accuracy": tf.metrics.accuracy(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 88 | "TP": tf.metrics.true_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 89 | "FN": tf.metrics.false_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 90 | "TN": tf.metrics.true_negatives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 91 | "FP": tf.metrics.false_positives(labels=tf.argmax(input=labels, axis=1), predictions=predictions["classes"]), 92 | } 93 | return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deep multi-view feature learning 2 | # 3 | ## Abstract 4 |   Epilepsy is a common neurological illness caused by abnormal discharge of brain neurons, where epileptic seizure could lead to life-threatening emergencies. By analyzing the encephalogram (EEG) signals of patients with epilepsy, their conditions can be monitored so that epileptic seizure can be detected and intervened in time. In epilepsy research, use of appropriate methods to obtain effective features is of great importance to the detection accuracy. In order to obtain features that can produce better detection results, this paper proposes a multi-view deep feature extraction method. The method first uses fast Fourier transform (FFT) and wavelet packet decomposition (WPD) to construct the initial multi-view features. Convolutional neural network (CNN) is then used to automatically learn the deep feature from the initial multi-view features, which can reduce the dimensionality and obtain features with better ability for seizure identification. Furthermore, the multi-view Takagi-Sugeno-Kang fuzzy system (MV-TSK-FS), an interpretable rule-based classifier, is used to obtain a classification model with stronger generalizability based on the obtained deep multi-view features. Experimental studies show that the proposed multi-view deep feature extraction method has better performance than common feature extraction methods such as principal component analysis (PCA), FFT and WPD. The performance of classification using the multi-view deep features is better than that using single-view deep features. 5 | ## author 6 | Xiaobin Tian, Zhaohong Deng, Senior Member, IEEE, Kup-Sze Choi, Dongrui Wu, Senior Member, 7 | IEEE, Bin Qin, Jun Wan, Hongbin Shen, Shitong Wang 8 | ## using this code 9 | ``` 10 | ├── data 11 | | ├──raw\_data 12 | ├──preprocessing 13 | | ├──preprocessing_data.m 14 | | ├──load_data.m 15 | | ├──domain_transform.m 16 | ├──CNN\_feature\_extracting 17 | | | ├──feature_extracting.py 18 | | | ├──view1_CNNmodel.py 19 | | | ├──view2_CNNmodel.py 20 | | | ├──view3_CN 21 | ├──mult\_TSK\_FS 22 | | | ├──auto_expt_mul_TSK.m 23 | | | ├──confusion_matrix.m 24 | | | ├──expt_mul_TSK.m 25 | | | ├──fromXtoZ.m 26 | | | ├──lab2vec.m 27 | | | ├──preproc.m 28 | | | ├──test_mul_TSK.m 29 | | | ├──test_TSK_FS.m 30 | | | ├──train_mul_TSK.m 31 | | | ├──train_TSK_FS.m 32 | | | ├──vec2lab.m 33 | ``` 34 | 1.Please set the original datset in "data/raw_data". 35 | 36 | 2.Run "/preprocessing/preprocessing_data.m" using matlab and get the initial multi-view EEG features. 37 | 38 | 3.python3 is needed. Your environment should include numpy, scipy and tensorflow. Run "/CNN\_feature\_extracting/feature_extracting.py" using python3 and get the deep multi-view features. 39 | 40 | 4.Run "/mult\_TSK\_FS/auto_expt_mul_TSK.m" using matlab and calculate the performance of this study. -------------------------------------------------------------------------------- /data/raw_data/data1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Txiaobin/deep-multi-view-feature-learning/665a27f72b69e56be6893d4412480e732db4d69d/data/raw_data/data1.mat -------------------------------------------------------------------------------- /data/raw_data/data2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Txiaobin/deep-multi-view-feature-learning/665a27f72b69e56be6893d4412480e732db4d69d/data/raw_data/data2.mat -------------------------------------------------------------------------------- /mult_TSK_FS/auto_expt_mul_TSK.m: -------------------------------------------------------------------------------- 1 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | % 3 | % load and preprocess dataset 4 | % construction the multi-view TSK fuzzy system 5 | % Calculate the performance of the constructed system 6 | 7 | clear; 8 | clc; 9 | data_num = 1; 10 | folds_num = 5; 11 | mean_result = zeros(folds_num, 5); 12 | result = zeros(2,5); 13 | for k = 1:folds_num 14 | load(['../data/feature/fold_' num2str(k) '/data_' num2str(data_num) '_train.mat']); 15 | load(['../data/feature/fold_' num2str(k) '/data_' num2str(data_num) '_predict.mat']); 16 | mulview_tr_cell = {tr_X_1; tr_X_2; tr_X_3}; 17 | mulview_te_cell = {te_X_1; te_X_2; te_X_3}; 18 | [ best_acc_result, TSK_result ] = expt_mul_TSK( mulview_tr_cell, mulview_te_cell, tr_Y, te_Y, k); 19 | mean_result(k,1) = mean_result(k,1) + best_acc_result.acc_mean; 20 | mean_result(k,2) = mean_result(k,2) + best_acc_result.sen_mean; 21 | mean_result(k,3) = mean_result(k,3) + best_acc_result.spe_mean; 22 | end 23 | result(1,:) = mean(mean_result); 24 | save(['../data/result/data' num2str(data_num) '_result.mat'], 'result', 'mean_result'); -------------------------------------------------------------------------------- /mult_TSK_FS/confusion_matrix.m: -------------------------------------------------------------------------------- 1 | function [ accuracy, sensitivity, specificity ] = ... 2 | confusion_matrix(labels, te_Y ) 3 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 4 | % 5 | % Calculate the confusion matrix of the data set based on the predicted values 6 | % Calculate performance indicators based on the confusion matrix 7 | % 8 | % labels:real label 9 | % te_Y:predicted label 10 | % accuracy, sensitivity, specificity:three performance indicators 11 | 12 | confusion_matrix = zeros(2,2); 13 | for j = 1:size(te_Y,1) 14 | if(te_Y(j) == labels(j)) 15 | if(labels(j) == 1) 16 | confusion_matrix(1,1) = confusion_matrix(1,1) + 1; 17 | else 18 | confusion_matrix(2,2) = confusion_matrix(2,2) + 1; 19 | end 20 | else 21 | if(labels(j) == 1) 22 | confusion_matrix(1,2) = confusion_matrix(1,2) + 1; 23 | else 24 | confusion_matrix(2,1) = confusion_matrix(2,1) + 1; 25 | end 26 | end 27 | end 28 | accuracy = (confusion_matrix(1,1) + confusion_matrix(2,2)) / size(labels,1); 29 | sensitivity = confusion_matrix(1,1) / (confusion_matrix(1,1) + confusion_matrix(1,2)); 30 | specificity = confusion_matrix(2,2) / (confusion_matrix(2,2) + confusion_matrix(2,1)); 31 | end -------------------------------------------------------------------------------- /mult_TSK_FS/expt_mul_TSK.m: -------------------------------------------------------------------------------- 1 | function [ best_acc_result, TSK_result ] = expt_mul_TSK( mulview_tr_cell, mulview_te_cell, tr_label, te_label, fold) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % construction the multi-view TSK fuzzy system 5 | % Calculate the performance of the constructed system 6 | 7 | view_nums = size(mulview_tr_cell,1); 8 | TSK_cell = cell(view_nums,4); 9 | folds_num = 5; 10 | options.view_nums = view_nums; 11 | maxIter = 10; 12 | options.maxIter = maxIter; 13 | lamda1s = 2.^(-6:6); 14 | lamda2s = 2.^(-6:6); 15 | lamda3s = 2.^(-6:6); 16 | n = size(tr_label,2); 17 | te_label = vec2lab(te_label); 18 | 19 | % zero-centered train data of each view 20 | for view_num = 1:view_nums 21 | acc_data = mulview_tr_cell{view_num,1}; 22 | acc_data = mapminmax(acc_data', 0, 1)'; 23 | mulview_tr_cell{view_num,1} = acc_data; 24 | end 25 | % zero-centered test data of each view 26 | for view_num = 1:view_nums 27 | acc_data = mulview_te_cell{view_num,1}; 28 | acc_data = mapminmax(acc_data', 0, 1)'; 29 | mulview_te_cell{view_num,1} = acc_data; 30 | end 31 | 32 | 33 | % train classifier of each view 34 | TSK_result = cell(view_nums,1); 35 | for view_num = 1:view_nums 36 | tr_data = mulview_tr_cell{view_num,1}; 37 | te_data = mulview_te_cell{view_num,1}; 38 | [pg, v, b, best_TSK_result] = train_TSK_FS( tr_data, te_data, tr_label, te_label, folds_num, view_num, fold); 39 | TSK_cell{ view_num, 1 } = pg; 40 | TSK_cell{ view_num, 2 } = v; 41 | TSK_cell{ view_num, 3 } = b; 42 | TSK_cell{ view_num, 4 } = 1/view_nums; 43 | TSK_result{ view_num, 1 } = best_TSK_result; 44 | end 45 | 46 | best_acc_te = 0; 47 | a = 0; 48 | for lamda1 = lamda1s 49 | a = a + 1; 50 | b = 0; 51 | for lamda2 = lamda2s 52 | b = b + 1; 53 | c = 0; 54 | for lamda3 = lamda3s 55 | c = c + 1; 56 | options.lamda1 = lamda1; 57 | options.lamda2 = lamda2; 58 | options.lamda3 = lamda3; 59 | result = zeros(folds_num,1); 60 | try 61 | for fold_num = 1:folds_num 62 | [best_TSK_cell, best_lamada_scale] = train_mul_TSK( mulview_tr_cell, TSK_cell, tr_label, options); 63 | [te_Y] = test_mul_TSK( mulview_te_cell ,best_TSK_cell, view_nums, n); 64 | te_Y = vec2lab(te_Y); 65 | [ acc, sen, spe ] = confusion_matrix(te_label, te_Y); 66 | result(fold_num,1) = acc; 67 | result(fold_num,2) = sen; 68 | result(fold_num,3) = spe; 69 | end 70 | catch err 71 | disp(err); 72 | warning('Something wrong when using function pinv!'); 73 | break; 74 | end 75 | acc_te_mean = mean(result(:,1)); 76 | sen_te_mean = mean(result(:,2)); 77 | spe_te_mean = mean(result(:,3)); 78 | if (acc_te_mean>best_acc_te) 79 | best_acc_te = acc_te_mean; 80 | best_acc_result.best_model = best_TSK_cell; 81 | best_acc_result.acc_mean = acc_te_mean; 82 | best_acc_result.sen_mean = sen_te_mean; 83 | best_acc_result.spe_mean = spe_te_mean; 84 | best_acc_result.lamda_scale = best_lamada_scale; 85 | end 86 | fprintf('train mul TSK FS:%d/5\nNumber of iterations:%d-----%d-----%d\n', fold, a, b, c); 87 | fprintf('best acc result:\nacc:%.4f sen:%.4f spe:%.4f\n',best_acc_result.acc_mean, best_acc_result.sen_mean, best_acc_result.spe_mean); 88 | end %end lamda3s 89 | end %end lamda2s 90 | end %end lamda1s 91 | -------------------------------------------------------------------------------- /mult_TSK_FS/fromXtoZ.m: -------------------------------------------------------------------------------- 1 | function zt=fromXtoZ(data,v,b) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % Convert X to Xg according to the antecedent parameters 5 | % 6 | % data:X 7 | % zt:Xg 8 | 9 | N = size(data, 1); 10 | xt = [data, ones(N,1)]; 11 | [M, d] = size(v); 12 | 13 | for i = 1:M 14 | v1 = repmat(v(i,:), N,1); 15 | bb = repmat(b(i,:), N,1); 16 | wt(:,i) = exp(-sum((data - v1) .^ 2 ./ bb, 2)); 17 | end 18 | 19 | wt2 = sum(wt, 2); 20 | wt = wt ./ repmat(wt2, 1, M); 21 | 22 | zt = []; 23 | for i=1:M 24 | wt1 = wt(:,i); 25 | wt2 = repmat(wt1, 1, d+1); 26 | zt = [zt, xt .* wt2]; 27 | end 28 | Mask = isnan(zt); 29 | zt(Mask) = 1e-5; 30 | %zt:N*K -------------------------------------------------------------------------------- /mult_TSK_FS/lab2vec.m: -------------------------------------------------------------------------------- 1 | function [ vectors ] = lab2vec( labels ) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % convert the scalar of the label to a vector(one of hot) 5 | 6 | N=length(labels); 7 | M=max(labels); 8 | 9 | vectors=zeros(N,M); 10 | for m=1:M 11 | indices=(labels==m); 12 | vectors(indices,m)=1; 13 | end 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /mult_TSK_FS/preproc.m: -------------------------------------------------------------------------------- 1 | function [v,U]=preproc(data,M) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % implementation of a Hierarchical Clustering Method 5 | % a detailed description is described in the following paper 6 | % :Transfer Representation Learning with TSK Fuzzy System, pengxu 7 | % :Deep multi-view feature learning for epileptic seizure detection, xiaobin tian 8 | % 9 | % data:input data 10 | % M:Number of categories 11 | % v,U:the antecedent parameter of TSK fuzzy system 12 | 13 | [N, d]=size(data); 14 | h = 1; 15 | 16 | if M > N 17 | M = N; 18 | end 19 | 20 | if M > 1 21 | corrDist = pdist(data, 'euclidean'); 22 | clusterTree = linkage(corrDist, 'average'); 23 | clusters = cluster(clusterTree, 'maxclust', M); 24 | v_std = std(data); 25 | else 26 | v_std = std(data); 27 | clusters = ones(N, 1); 28 | end 29 | 30 | v = zeros(M, d); 31 | delta = zeros(M, d); 32 | 33 | for i = 1:M 34 | hi = find(clusters == i); 35 | tem = data(hi, :); 36 | if length(hi) > 1 37 | v(i, :) = mean(tem); 38 | delta(i, :) = std(tem) + 1e-6; 39 | else 40 | v(i, :) = tem; 41 | delta(i, :) = v_std + 1e-6; 42 | end 43 | end 44 | delta = delta/h; 45 | U = delta; -------------------------------------------------------------------------------- /mult_TSK_FS/test_TSK_FS.m: -------------------------------------------------------------------------------- 1 | function [Y] = test_TSK_FS( test_data , pg, v, b) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % Calculate the predicted values of test data based on pg, v, b. 5 | % 6 | % test_data:test dataset 7 | % Y:predicted label 8 | 9 | test_data = fromXtoZ(test_data,v,b); 10 | Y = test_data*pg; 11 | -------------------------------------------------------------------------------- /mult_TSK_FS/test_mul_TSK.m: -------------------------------------------------------------------------------- 1 | function [Y_te] = test_mul_TSK( test_data_cell ,TSK_cell, view_nums, c) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % Calculate the predicted values of test data based on pg, v, b. 5 | % 6 | % test_data_cell:test data of multi-view dataset 7 | % c;the number of categories 8 | % Y_te:predicted label 9 | 10 | Y_te = zeros( size( test_data_cell{1,1},1), c); 11 | 12 | for t = 1:view_nums 13 | acc_pg = TSK_cell{t,1}; 14 | acc_v = TSK_cell{t,2}; 15 | acc_b = TSK_cell{t,3}; 16 | acc_w = TSK_cell{t,4}; 17 | acc_x = test_data_cell{t,1}; 18 | acc_x = fromXtoZ(acc_x,acc_v,acc_b); 19 | FS_output = acc_x*acc_pg; 20 | Y_te = Y_te + acc_w*FS_output; 21 | end -------------------------------------------------------------------------------- /mult_TSK_FS/train_TSK_FS.m: -------------------------------------------------------------------------------- 1 | function [best_pg, best_v, best_b, best_TSK_result] = train_TSK_FS( tr_data, te_data, tr_label, te_label, folds_num, view_num, k) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % train classifier of each view 5 | 6 | Ms = [ 2:1:6 ]; 7 | lamdas = [0,2.^(-5:5)]; 8 | a = 0; 9 | best_acc_mean = 0; 10 | for lamda = lamdas 11 | a = a + 1; 12 | c = 0; 13 | for M = Ms 14 | c = c + 1; 15 | result = zeros(folds_num,3); 16 | for fold=1:folds_num 17 | [v,b] = preproc(tr_data, M); 18 | Xg = fromXtoZ(tr_data,v,b); %Xg:N*K 19 | Xg1 = Xg'*Xg; 20 | pg = pinv(Xg1 + lamda*eye( size(Xg1)))*Xg'*tr_label; %Solving the consequent parameters of the TSK-FS 21 | [te_Y] = test_TSK_FS( te_data , pg, v, b); 22 | te_Y = vec2lab(te_Y); 23 | [ acc, sen, spe ] = confusion_matrix(te_label, te_Y ); 24 | result(fold,1)=acc; 25 | result(fold,2)=sen; 26 | result(fold,3)=spe; 27 | end 28 | acc_te_mean = mean(result(:,1)); 29 | sen_te_mean = mean(result(:,2)); 30 | spe_te_mean = mean(result(:,3)); 31 | if acc_te_mean>best_acc_mean 32 | best_acc_mean = acc_te_mean; 33 | best_TSK_result.acc = acc_te_mean; 34 | best_TSK_result.sen = sen_te_mean; 35 | best_TSK_result.spe = spe_te_mean; 36 | best_pg = pg; 37 | best_v = v; 38 | best_b = b; 39 | end 40 | fprintf('train TSK FS:%d/5------view:%d\nNumber of iterations:%d/%d------%d/%d\n', k, view_num, a, size(lamdas,2), c, size(Ms,2)); 41 | fprintf('best acc result:\nacc:%.4f sen:%.4f spe:%.4f\n\n',best_TSK_result.acc, best_TSK_result.sen, best_TSK_result.spe); 42 | end %end M 43 | end %end lamda 44 | -------------------------------------------------------------------------------- /mult_TSK_FS/train_mul_TSK.m: -------------------------------------------------------------------------------- 1 | function [TSK_cell, lamda_scale] = train_mul_TSK( mulview_data_cell, TSK_cell, Y, options) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % train classifier of multi-view 5 | 6 | view_nums = options.view_nums; 7 | lamda_scale = zeros(3, 1); 8 | 9 | c = size(Y, 2); 10 | N = size( mulview_data_cell{1,1}, 1); 11 | lamda1 = options.lamda1; 12 | lamda2 = options.lamda2; 13 | lamda3 = options.lamda3; 14 | maxIter = options.maxIter; 15 | 16 | for i = 1:maxIter 17 | sum_weight = 0; 18 | for view_num = 1:view_nums 19 | temp_pg = TSK_cell{ view_num, 1 }; 20 | temp_v = TSK_cell{ view_num, 2 }; 21 | temp_b = TSK_cell{ view_num, 3 }; 22 | temp_x = mulview_data_cell{view_num,1}; 23 | temp_x = fromXtoZ(temp_x,temp_v,temp_b); 24 | sum_variance = (sum(temp_x * temp_pg - Y))*sum(temp_x * temp_pg - Y)'; 25 | sum_variance = exp(-lamda3*sum_variance); 26 | sum_weight = sum_weight+sum_variance; 27 | end 28 | for view_num = 1:view_nums 29 | acc_pg = TSK_cell{ view_num, 1 }; 30 | acc_v = TSK_cell{ view_num, 2 }; 31 | acc_b = TSK_cell{ view_num, 3 }; 32 | acc_x = mulview_data_cell{view_num,1}; 33 | x = fromXtoZ(acc_x,acc_v,acc_b); 34 | variance = (sum(x * acc_pg - Y))*sum(x * acc_pg - Y)'; 35 | acc_w = exp(-lamda3*variance)/sum_weight; 36 | sum_y = zeros(N,c); 37 | for j = 1:view_nums 38 | if j ~= view_num 39 | temp_pg = TSK_cell{j,1}; 40 | temp_v = TSK_cell{j,2}; 41 | temp_b = TSK_cell{j,3}; 42 | temp_x = mulview_data_cell{j,1}; 43 | temp_x = fromXtoZ(temp_x,temp_v,temp_b); 44 | sum_y = sum_y + temp_x*temp_pg; 45 | lamda_scale(1,1) = lamda1; 46 | lamda_scale(2,1) = lamda2; 47 | lamda_scale(3,1) = lamda3; 48 | end 49 | end 50 | y_cooperate = sum_y/(view_nums - 1); 51 | z = acc_w*(x)'*x; 52 | TSK_cell{ view_num, 1 } = pinv( z + lamda1 * eye( size( z)) +lamda2*(x)'*x)*(acc_w*x'*Y+lamda2*x'*y_cooperate); 53 | TSK_cell{ view_num, 4 } = acc_w; 54 | end %end view_num 55 | end 56 | -------------------------------------------------------------------------------- /mult_TSK_FS/vec2lab.m: -------------------------------------------------------------------------------- 1 | function [ labels ] = vec2lab( vectors ) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % convert the vector(one of hot) of the label to a scalar 5 | 6 | 7 | 8 | [~,labels]=max(vectors,[],2); 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /preprocessing/domain_transform.m: -------------------------------------------------------------------------------- 1 | function [ X_1, X_2, X_3]=domain_transform(X) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % using FFT and WPT to obtain the frequency features 5 | % and time-frequency features of the dataset 6 | % 7 | % the adopted wavelet basis function is Daubechies (dbN) 8 | % the order of the wavelet function is set to 4 9 | % the level of decomposition layers of the wavelet transform is 6 10 | % They can all change according to your own situation 11 | % 12 | % X:features of the dataset; 13 | % X_1:time features; 14 | % X_2:frequency features; 15 | % X_3:time-frequency features; 16 | 17 | L = size(X, 1); 18 | chan = size(X, 2); 19 | num = size(X, 3); 20 | 21 | X_1 = []; 22 | X_2 = []; 23 | X_3 = []; 24 | % processing dataset into time features 25 | fprintf(' transform time feature\n'); 26 | for i = 1:num 27 | a = []; 28 | for j = 1:chan 29 | a = cat(1, a, X(:,j,i)); 30 | end 31 | X_1 = cat(1, X_1, a'); 32 | end 33 | % processing dataset into frequency features, using FFT 34 | fprintf(' transform frequency feature\n'); 35 | NFFT = 2 ^ nextpow2(L); 36 | for i = 1:num 37 | b = []; 38 | for j = 1:chan 39 | a = fft(X(:,j,i),NFFT) / L; 40 | a = 2 * abs(a); 41 | b = cat(1, b, a(4:30)); 42 | end 43 | X_2 = cat(1, X_2, b'); 44 | end 45 | % processing dataset into time-frequency features, using WPD 46 | fprintf(' transform time-frequency feature\n'); 47 | WPD_layers = 6; 48 | wavelet_basis = 'db4'; 49 | fs = 256; 50 | for i = 1:num 51 | a = []; 52 | for j = 1:chan 53 | wpt = wpdec(X(:,j,i), WPD_layers, wavelet_basis); 54 | [SPEC,~,~] = wpspectrum(wpt,fs); 55 | a = cat(2, a, reshape(SPEC(2:15,:)', [14 * 256,1])'); 56 | end 57 | X_3 = cat(1, X_3, a); 58 | end 59 | end -------------------------------------------------------------------------------- /preprocessing/load_data.m: -------------------------------------------------------------------------------- 1 | function [ X, Y ]=load_data(filename) 2 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 3 | % 4 | % load and preprocessed dataset 5 | % part of the non-seizure data is abandoned 6 | % and over-sampling method is applied for the seizure data, 7 | % where using sliding window to capture clips and allowing overlapping between two windows. 8 | % this approach reduces the difference between the number of non-seizure and seizure data. 9 | % 10 | % filename:the filename of dataset 11 | % X:features of the dataset 12 | % Y:labels of the dataset(one-of-hot) 13 | 14 | overlap_ratio = 3/4; 15 | segment_size = 256; 16 | overlap_size = segment_size*(1-overlap_ratio); 17 | X = []; 18 | Y = []; 19 | load(filename); 20 | %split segment using sliding windows 21 | for i = 0 : (size(seizure_data,1)-segment_size) / overlap_size 22 | X = cat(3, X, seizure_data(1 + overlap_size * i:segment_size + overlap_size * i,:)); 23 | Y = cat(1, Y, [0, 1]); 24 | end 25 | for i = 0 : (size(nonseizure_data,1)-segment_size) / segment_size 26 | X = cat(3, X, nonseizure_data(1 + segment_size * i:segment_size + segment_size * i,:)); 27 | Y = cat(1, Y, [1, 0]); 28 | end 29 | %disrupt dataset 30 | rank = randperm(size(X, 3)); 31 | X = X(:,:,rank); 32 | Y = Y(rank,:); -------------------------------------------------------------------------------- /preprocessing/preprocessing_data.m: -------------------------------------------------------------------------------- 1 | % 2019-05-07 XiaobinTian xiaobin9652@163.com 2 | % 3 | % preprocessed dataset 4 | % construction of initial multi-view EEG features 5 | 6 | clc; 7 | clear; 8 | for k = 1:8 9 | filename = ['../data/raw_data/data' num2str(k) '.mat']; 10 | fprintf('load data_set:%d\n',k); 11 | [ X, Y ]=load_data(filename); 12 | 13 | fprintf('transform data_set:%d\n',k); 14 | [ X_1, X_2, X_3 ]=domain_transform(X); 15 | 16 | X_1 = single(X_1); 17 | X_2 = single(X_2); 18 | X_3 = single(X_3); 19 | 20 | X = {X_1; X_2; X_3}; 21 | 22 | fprintf('save data_set:%d\n',k); 23 | save(strcat('../data/domain_feature/train_data',num2str(k),'.mat'), 'X', 'Y'); 24 | end --------------------------------------------------------------------------------