image.png

    实例:

    1. # 导入模块
    2. import numpy as np
    3. import random
    4. import torch
    5. import torch.nn as nn
    6. import torch.nn.functional as F
    7. from torch.utils.data import DataLoader, Dataset, TensorDataset
    8. from torchvision import models
    9. net = models.resnet18(pretrained=True)
    10. # 创建一个数据集
    11. X = torch.rand(500,3, 32, 32)
    12. Y = torch.rand(500, 1)
    13. # random shuffle
    14. index = [i for i in range(len(X))]
    15. random.shuffle(index)
    16. X = X[index]
    17. Y = Y[index]
    18. def get_kfold_data(k, i, X, y):
    19. # 返回第 i+1 折 (i = 0 -> k-1) 交叉验证时所需要的训练和验证数据,X_train为训练集,X_valid为验证集
    20. fold_size = X.shape[0] // k # 每份的个数:数据总条数/折数(组数)
    21. val_start = i * fold_size
    22. if i != k - 1:
    23. val_end = (i + 1) * fold_size
    24. X_valid, y_valid = X[val_start:val_end], y[val_start:val_end]
    25. X_train = torch.cat((X[0:val_start], X[val_end:]), dim=0)
    26. y_train = torch.cat((y[0:val_start], y[val_end:]), dim=0)
    27. else: # 若是最后一折交叉验证
    28. X_valid, y_valid = X[val_start:], y[val_start:] # 若不能整除,将多的case放在最后一折里
    29. X_train = X[0:val_start]
    30. y_train = y[0:val_start]
    31. return X_train, y_train, X_valid, y_valid
    32. def traink(model, X_train, y_train, X_val, y_val, BATCH_SIZE, learning_rate, TOTAL_EPOCHS):
    33. train_loader = DataLoader(TensorDataset(X_train, y_train), BATCH_SIZE, shuffle=True)
    34. val_loader = DataLoader(TensorDataset(X_val, y_val), BATCH_SIZE, shuffle=True)
    35. criterion = nn.CrossEntropyLoss()
    36. optimizer = torch.optim.Adam(params=model.parameters(), lr=learning_rate)
    37. losses = []
    38. val_losses = []
    39. train_acc = []
    40. val_acc = []
    41. for epoch in range(TOTAL_EPOCHS):
    42. model.train()
    43. correct = 0 # 记录正确的个数,每个epoch训练完成之后打印accuracy
    44. for i, (images, labels) in enumerate(train_loader):
    45. images = images.float()
    46. labels = torch.squeeze(labels.type(torch.LongTensor))
    47. optimizer.zero_grad() # 清零
    48. outputs = model(images)
    49. # 计算损失函数
    50. loss = criterion(outputs, labels)
    51. loss.backward()
    52. optimizer.step()
    53. losses.append(loss.item())
    54. # 计算正确率
    55. y_hat = model(images)
    56. pred = y_hat.max(1, keepdim=True)[1]
    57. correct += pred.eq(labels.view_as(pred)).sum().item()
    58. if (i + 1) % 10 == 0:
    59. # 每10个batches打印一次loss
    60. print('Epoch : %d/%d, Iter : %d/%d, Loss: %.4f' % (epoch + 1, TOTAL_EPOCHS,
    61. i + 1, len(X_train) // BATCH_SIZE,
    62. loss.item()))
    63. accuracy = 100. * correct / len(X_train)
    64. print('Epoch: {}, Loss: {:.5f}, Training set accuracy: {}/{} ({:.3f}%)'.format(
    65. epoch + 1, loss.item(), correct, len(X_train), accuracy))
    66. train_acc.append(accuracy)
    67. # 每个epoch计算测试集accuracy
    68. model.eval()
    69. val_loss = 0
    70. correct = 0
    71. with torch.no_grad():
    72. for i, (images, labels) in enumerate(val_loader):
    73. images = images.float()
    74. labels = torch.squeeze(labels.type(torch.LongTensor))
    75. optimizer.zero_grad()
    76. y_hat = model(images)
    77. loss = criterion(y_hat, labels).item() # batch average loss
    78. val_loss += loss * len(labels) # sum up batch loss
    79. pred = y_hat.max(1, keepdim=True)[1] # get the index of the max log-probability
    80. correct += pred.eq(labels.view_as(pred)).sum().item()
    81. val_losses.append(val_loss / len(X_val))
    82. accuracy = 100. * correct / len(X_val)
    83. print('Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.3f}%)\n'.format(
    84. val_loss, correct, len(X_val), accuracy))
    85. val_acc.append(accuracy)
    86. return losses, val_losses, train_acc, val_acc
    87. def k_fold(k, X_train, y_train, num_epochs=3, learning_rate=0.0001, batch_size=16):
    88. train_loss_sum, valid_loss_sum = 0, 0
    89. train_acc_sum, valid_acc_sum = 0, 0
    90. for i in range(k):
    91. print('*' * 25, '第', i + 1, '折', '*' * 25)
    92. data = get_kfold_data(k, i, X_train, y_train) # 获取k折交叉验证的训练和验证数据
    93. #net = net() # 实例化模型(某已经定义好的模型)
    94. # 每份数据进行训练
    95. train_loss, val_loss, train_acc, val_acc = traink(net, *data, batch_size, learning_rate, num_epochs)
    96. print('train_loss:{:.5f}, train_acc:{:.3f}%'.format(train_loss[-1], train_acc[-1]))
    97. print('valid loss:{:.5f}, valid_acc:{:.3f}%\n'.format(val_loss[-1], val_acc[-1]))
    98. train_loss_sum += train_loss[-1]
    99. valid_loss_sum += val_loss[-1]
    100. train_acc_sum += train_acc[-1]
    101. valid_acc_sum += val_acc[-1]
    102. print('\n', '#' * 10, '最终k折交叉验证结果', '#' * 10)
    103. print('average train loss:{:.4f}, average train accuracy:{:.3f}%'.format(train_loss_sum / k, train_acc_sum / k))
    104. print('average valid loss:{:.4f}, average valid accuracy:{:.3f}%'.format(valid_loss_sum / k, valid_acc_sum / k))
    105. return
    106. k_fold(10, X, Y, num_epochs=3, learning_rate=0.0001, batch_size=16)