语义分割实现地表建筑物识别5 模型训练与验证

语义分割实现地表建筑物识别5 模型训练与验证

学习目标

  • 掌握数据划分方法和具体实践
  • 掌握模型训练&模型调参过程

数据划分

  • 训练集、验证集、测试集
  • 划分方法:留出法、交叉验证法、自助采样法

模型调参流程

  1. 初步构建简单的CNN模型,跑通训练、验证和预测的流程
  2. 简单CNN模型的损失较大,尝试增加模型复杂度,并观察验证集精度
  3. 在增加模型复杂度的同时增加数据扩增方法,直至验证集精度不变
    目前还处于baseline的跑通训练、验证阶段。
    调参部分需要根据训练误差、偏差判断需要增加模型复杂度还是通过数据扩增增加训练集数量、模型需要正则化。

使用Pytorch完成CNN的训练和验证

import torch.utils.data as D 

BATCH_SIZE = 10
EPOCHES = 5
best_loss = 10

# 划分训练集和验证集
dataset = TianChiDataset(
    train_mask['name'].values,
    train_mask['mask'].fillna('').values,
    trfm, False)

valid_idx, train_idx = [], []
for i in range(len(dataset)):
    if i % 7 == 0:
        valid_idx.append(i)
#     else:
    elif i % 7 == 1:
        train_idx.append(i)
        
train_ds = D.Subset(dataset, train_idx)
valid_ds = D.Subset(dataset, valid_idx)

# 构造训练集和验证集
train_loader = D.DataLoader(
    train_ds, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)

val_loader = D.DataLoader(
    valid_ds, batch_size=BATCH_SIZE, shuffle=False, num_workers=0)
       
def train(train_loader,model,criterion,optimizer):
    # 切换模型为训练模式
    model.train()
    losses = []
    for image,target in tqdm_notebook(train_loader):
        # 正向传播
        image, target = image.to(DEVICE),target.float().to(DEVICE)
        optimizer.zero_grad()
        output = model(image)['out']        
        # 计算损失
        loss = criterion(output, target)
        # 反向传播
        loss.backward()
        optimizer.step()
        losses.append(loss.item())
    return losses

def validate(val_loader,model,criterion):
    # 切换模型为预测模型
    model.eval()
    val_loss = []

    # 不记录模型梯度信息
    with torch.no_grad():
        for i,(image,target) in enumerate(val_loader):
            # 正向传播
            image, target = image.to(DEVICE), target.float().to(DEVICE)
            output = model(image)['out']
            # 计算损失  
            loss = criterion(output, target) 
            losses.append(loss.item())
    return val_loss

# 模型训练与验证过程
model = Model1()
raw_line = '{:6d}' + '\u2502{:7.3f}'*2 + '\u2502{:6.2f}'
criterion = nn.CrossEntropyLoss(size_average=False)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4, weight_decay=1e-3)
best_loss = 1000.0
for epoch in range(1, EPOCHES+1):
    print('Epoch:',epoch)
    start_time = time.time()
    losses = train(train_loader,model,criterion,optimizer)
    val_loss = validate(val_loader,model,criterion)
    print(raw_line.format(epoch,np.array(losses).mean(),val_loss,
    (time.time()-start_time)/60**1))
    if val_loss < best_loss:
        best_loss = val_loss
        torch.save(model.state_dict(),'./model_best.pth')

## 保存最优验证集模型
torch.save(model_object.state_dict(),'model_best.pth')
model.load_state_dict(torch.load('model_best.pth'))

# 模型预测测试集结果
test_mask = pd.read_csv('./test_a_samplesubmit.csv', sep='\t', names=['name', 'mask'])
test_mask['name'] = test_mask['name'].apply(lambda x: './test_a/' + x)

for idx, name in enumerate(tqdm_notebook(test_mask['name'].iloc[:])):
    image = cv2.imread(name)
    image = trfm(image)
    with torch.no_grad():
        image = image.to(DEVICE)[None]
        score = model(image)['out'][0][0]
        score_sigmoid = score.sigmoid().cpu().numpy()
        score_sigmoid = (score_sigmoid > 0.5).astype(np.uint8)
        score_sigmoid = cv2.resize(score_sigmoid, (512, 512))
        
    subm.append([name.split('/')[-1], rle_encode(score_sigmoid)])
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值