About leave-one-subject-out (LOSO) cross-validation strategy
pwjworks opened this issue · 4 comments
论文并没有做留一实验,我添加了几行代码,进行了SEED3的留一交叉验证实验,发现性能不能达到论文的准确率,下面是结果:
Cross-subject: [tensor(89.7466), tensor(78.7861), tensor(79.6995), tensor(84.5021), tensor(92.5751), tensor(77.3129), tensor(79.3164), tensor(64.1426), tensor(89.2163), tensor(94.6376), tensor(89.1279), tensor(75.4862), tensor(79.9352), tensor(86.2994), tensor(82.5280), tensor(76.9299), tensor(87.6842), tensor(81.5557), tensor(75.3094), tensor(66.2935), tensor(74.2487), tensor(79.4343), tensor(64.2899), tensor(98.0554), tensor(78.6093), tensor(98.0554), tensor(90.9546), tensor(85.8574), tensor(83.5887), tensor(73.0112), tensor(82.1155), tensor(89.0395), tensor(89.7761), tensor(65.3801), tensor(66.9417), tensor(47.1126), tensor(78.2557), tensor(66.4702), tensor(69.1220), tensor(90.1296), tensor(57.8963), tensor(84.2369), tensor(80.5245), tensor(88.1850), tensor(98.0554)]
Cross-subject mean: 80.23178 std: 10.919936
其中,每三个数字代表一个被试的准确率。
请问作者做过相关的实验吗?问题出在哪里?
我的运行环境是:
os: Ubuntu 18.05
gpu: RTX3090*1
python: 3.8.11
pytorch: 1.10+cu113
下面是我修改的代码:
# msmdaer.py
# cross-validation, 15 个被试的留一实验
for subject_id in range(15):
for i in range(3):
csub.append(cross_subject(data_tmp, label_tmp, i, subject_id, category_number,
batch_size, iteration, lr, momentum, log_interval))
# 传入了subjec id
# msmdaer.py
def cross_subject(data, label, session_id, subject_id, category_number, batch_size, iteration, lr, momentum, log_interval):
one_session_data, one_session_label = copy.deepcopy(
data[session_id]), copy.deepcopy(label[session_id])
# one_session_data, one_session_label = copy.deepcopy(
# data), copy.deepcopy(label)
train_idxs = list(range(15))
del train_idxs[subject_id]
test_idx = subject_id
target_data, target_label = one_session_data[test_idx,
:], one_session_label[test_idx, :]
source_data, source_label = copy.deepcopy(
one_session_data[train_idxs, :]), copy.deepcopy(one_session_label[train_idxs, :])
del one_session_label
del one_session_data
.......
#util.py
def load_data(dataset_name):
'''
description: get all the data from one dataset
param {type}
return {type}:
data: list 3(sessions) * 15(subjects), each data is x * 310
label: list 3*15, x*1
'''
path, allmats = get_allmats_name(dataset_name)
data = [([0] * 15) for i in range(3)]
label = [([0] * 15) for i in range(3)]
for i in range(len(allmats)):
for j in range(len(allmats[0])):
mat_path = path + '/' + str(i+1) + '/' + allmats[i][j]
one_data, one_label = get_data_label_frommat(
mat_path, dataset_name, i)
data[i][j] = one_data.copy()
label[i][j] = one_label.copy()
return np.array(data), np.array(label)
Hi @pwjworks , 感谢您对我们工作的关注!
这是一个非常非常好的问题,在对比中,由于其他工作都没有公开代码,所以我要么是自己复现要么是直接引用对比工作中的数字。但是因为自己复现出来的结果和他们论文中的数字区别真的很大(~20%,不过不是LSLO),所以我认为虽然对比工作中有个别提到了他们是基于LSLO的,但是仍然不能让我信服,另外在对比工作的设置的话,就我所知的有些显著的工作我自己复现了后如果严格按照LSLO也是复现不出来,但是对于每个sub选取最高的session然后这15个session取平均后反而就达到论文的结果了,所以选sub最高的session我认为也是标准之一?
因此,这也是我刻意避免了的在这整一个数据库和论文中存在的问题,也就是我为了避免大量重复的,没有目的性的调参,在设计整个实验方案和模型的时候,只是单纯选择了最后一个sub作为target,其他14个作为source。如果按照LOSO的标准的话,那么整一套的工作和实验就直接是原本的15倍起(而且您跑过MS-MDA后应该能感觉出来,由于我们分支成了多个branch,所以训练所需要的时间也是指数级的增长的)。因此我最后折中选择了最后一个为target的方式,并且在论文中的Section III. B. Scenarios里给出了我们这种设置。
另外还有一个原因,就是在这篇论文和实验中,我选取的batch_size是256,但是结果来看其实小一点的bs效果是要好很多的,我认为bs设置小了后的LSLO的结果会高很多,但是我个人会比较倾向小bs虽然结果好但是泛化不够(个人观点),所以选的256。对比工作基本都没给bs的设置,所以我也不好说。您可以尝试下选用不同的bs和其他的超参,然后也可以对DAN做一样的实验(我自己也在跑,不过估计出结果得几天后),然后可以对比MS-MDA和DAN的结果,以及DAN复现结果和18年Li他们发的DAN在SEED上的结果的对比。这两个对比我认为会比较convincing。
再一次感谢您的问题!这确实是实验部分不够严谨的地方,同时也是我认为这个小领域里缺乏的一个统一的标准。
非常感谢您详细的回答!我的研究方向是使用图网络进行脑电情绪识别,目前我的工作是使用整段EEG数据(1 trial 1 sample)进行分类,我发现脑电数据分割成一秒一样本后准确率会下降很多(大概是数据不服从同一分布了?)而且难以提高准确率,因此可能需要进行迁移学习。很多脑电情绪识别论文都使用迁移学习,其中,MS-MDA是为数不多选择开源的项目,给了我非常大的启示。您提到的脑电情绪识别领域缺乏标准我是深感赞同的,因为很多相关论文的数据选取和数据处理都不尽相同而且很难去复现,很少有公布的代码。
后面我会继续关注您的工作,冬至快乐!