深度学习经验之谈(缓更)
1.验证集准确度一直高于训练集
验证集准确度在训练过程中比训练集高10个点左右。
如果数据集的选取与划分没有问题,大概率是因为训练集使用的很强的数据增强,和模型中使用dropout也有关系。
2.pytorch数据集划分以及分层k折交叉验证实现
因为pytorch没有直接实现的API,所以推荐使用sklearn包实现。
from sklearn.model_selection import train_test_split, StratifiedKFold
首先是普通的交叉验证,训练集和验证集按照比例划分
images_train, images_test, labels_train, labels_test = train_test_split(images_name, labels, test_size=0.2,random_state=5, stratify=labels)
输入可以使列表也可以是DataFrame格式的,test_size是划分比例,random_state打乱数据,随机种子相同,打乱的顺序也相同,stratify = labels 是指按照label的比例抽样,处理数据不平衡的问题。
下面是k折交叉验证,可以使用if fold == n:
的方式来确定每一折的数据,这样可以不用一次性训练完5种划分,可以分别计算
skf = StratifiedKFold(n_splits=5, random_state=5, shuffle=True)
for fold, (train_idx, val_idx) in enumerate(skf.split(images_train,labels_train)):
if fold == 3: # 这样写可以一折一折计算,此时是第四折,如果要一次性计算,把这个判断去掉即可
images_train_k = np.array(images_train)[train_idx]
labels_train_k = np.array(labels_train)[train_idx]
images_val = np.array(images_train)[val_idx]
labels_val = np.array(labels_train)[val_idx]
data_train = DatasetGenerator(image_names=images_train_k, labels=labels_train_k, transform1=transform_list1,
transform2=transformList2, set='train')
train_loader = torch.utils.data.DataLoader(dataset=data_train, batch_size=Batch_size,
shuffle=True, num_workers=4, pin_memory=True)
data_val = DatasetGenerator(image_names=images_val, labels=labels_val, transform1=transform_list_val1,
transform2=transformList2, set='val')
val_loader = torch.utils.data.DataLoader(dataset=data_val, batch_size=Batch_size,
shuffle=False, num_workers=4, pin_memory=True)
# 下面是训练
train_step
3. pytorch实现不平衡数据的过采样
因为pytorch dataloader的sampler用起来不习惯,所以自己在DatasetGenerator中实现一下,我的样本中1是0的五倍左右,所以对0样本做五倍的扩充,下面是实现的代码。我的是图像分类问题,输入的是图片地址列表和标签列表,在init中过采样即可,验证集不用过采样。
class DatasetGenerator(Dataset):
def __init__(self, image_names, labels, transform1=None, transform2=None, set='train'):
self.image_names = image_names
self.labels = labels
self.transform1 = transform1
self.transform2 = transform2
self.image_names_ag = []
self.labels_ag = []
self.set = set
for idx, label in enumerate(labels):
if label == 1:
self.image_names_ag.append(image_names[idx])
self.labels_ag.append(1)
if label == 0:
if set == 'train':
for i in range(5):
self.image_names_ag.append(image_names[idx])
self.labels_ag.append(0)
if set == 'val':
self.image_names_ag.append(image_names[idx])
self.labels_ag.append(0)
def __getitem__(self, index):
image_name = self.image_names_ag[index]
label = self.labels_ag[index]
image = cv2.imread(image_name)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = Image.fromarray(np.array(image))
if self.transform1 is not None:
image = self.transform1(image)
if self.transform2 is not None:
image = self.transform2(image)
return torch.FloatTensor(image), label
def __len__(self):
return len(self.image_names_ag)