PyTorch,tensorflow.通過學習可以快速掌握的兩個機器學習庫對應的內容.但是這兩個庫非常強大,下次換個題目還能不能自己寫代碼?還是需要系統(tǒng)的從基礎來學習才行啊.
import glob, json
from PILimport Image
from tqdmimport tqdm
import numpyas np
import pandasas pd
import torch
import torch.nnas nn
import torch.optimas optim
import torchvision.modelsas models
import torchvision.transformsas transforms
from torch.utils.data.datasetimport Dataset
class SVHNDataset(Dataset):
def __init__(self, img_path, img_label, transform=None):
self.img_path,self.img_label,self.transform = img_path, img_label, transform
def __getitem__(self, index):
img = Image.open(self.img_path[index]).convert('RGB')# 讀取數(shù)據(jù)
? ? ? ? img =self.transform(img)# 做相應變換
? ? ? ? if self.img_label:
lbl = np.array(self.img_label[index],dtype=np.int)# 制作標簽
? ? ? ? ? ? lbl =list(lbl)? + (5 -len(lbl)) * [10]# 標簽長度少于五的用10來填充
? ? ? ? ? ? return img, torch.from_numpy(np.array(lbl[:5]))
else:
return img
def __len__(self):
return len(self.img_path)
# 定義模型
class SVHN_Model1(nn.Module):
def __init__(self):
super(SVHN_Model1,self).__init__()
self.cnn = models.resnet50(pretrained=True)# 加載resnet50
? ? ? ? self.cnn.avgpool = nn.AdaptiveAvgPool2d(1)# 將平均池化改為自適應平均池化
? ? ? ? self.cnn = nn.Sequential(*list(self.cnn.children())[:-1])# 去除最后的線性層
? ? ? ? self.fc1,self.fc2,self.fc3 = nn.Linear(2048,11), nn.Linear(2048,11), nn.Linear(2048,11)
self.fc4,self.fc5 = nn.Linear(2048,11), nn.Linear(2048,11)
def forward(self, img):
feat =self.cnn(img)
feat = feat.view(feat.shape[0], -1)
c1,c2,c3 =self.fc1(feat),self.fc2(feat),self.fc3(feat)
c4,c5 =self.fc4(feat),self.fc5(feat)
return c1, c2, c3, c4, c5
def train(train_loader, model, criterion, optimizer):
model.train()# 切換模型為訓練模式
? ? train_loss = []
for input, targetin tqdm(train_loader):# 取出數(shù)據(jù)與對應標簽
? ? ? ? if use_cuda:# 如果是gpu版本
? ? ? ? ? ? input, target = input.cuda(), target.cuda()
target = target.long()
c0, c1, c2, c3, c4 = model(input)# 得到預測值
? ? ? ? loss = criterion(c0, target[:,0]) + criterion(c1, target[:,1]) + \
criterion(c2, target[:,2]) + criterion(c3, target[:,3]) + \
criterion(c4, target[:,4])# 計算loss
? ? ? ? optimizer.zero_grad()# 梯度清零
? ? ? ? loss.backward()# 反向傳播
? ? ? ? optimizer.step()# 參數(shù)更新
? ? ? ? train_loss.append(loss.item())
return np.mean(train_loss)
def predict(test_loader, model):
model.eval()# 切換模型為預測模型
? ? test_pred = []
with torch.no_grad():# 不記錄模型梯度信息
? ? ? ? for inputin tqdm(test_loader):
if use_cuda: input = input.cuda()
c0, c1, c2, c3, c4 = model(input)
if use_cuda:
output = np.concatenate([
c0.data.cpu().numpy(), c1.data.cpu().numpy(), c2.data.cpu().numpy(),# 將結果水平合并,即第一個字符索引為第一列到第十一列爵憎,
? ? ? ? ? ? ? ? ? ? c3.data.cpu().numpy(), c4.data.cpu().numpy()],axis=1)# 第二個字符為第十二列到第二十二列籽懦,依次往下
? ? ? ? ? ? else:
output = np.concatenate([
c0.data.numpy(), c1.data.numpy(), c2.data.numpy(),
c3.data.numpy(), c4.data.numpy()],axis=1)
test_pred.append(output)
test_pred = np.vstack(test_pred)# 將每個batch的結果垂直堆起來
? ? return test_pred
train_path, test_path = glob.glob('../input/train/*.png'), glob.glob('../input/test_a/*.png')# 讀取訓練數(shù)據(jù)和測試數(shù)據(jù)
train_path.sort(); test_path.sort()
train_json = json.load(open('../input/train.json'))#讀取訓練集標注文件
train_label = [train_json[x]['label']for xin train_json]# 拿出訓練集的標簽
trans_fun = transforms.Compose([
transforms.Resize((64,128)),# 將圖片裁剪為64*128
? ? ? ? ? ? ? ? transforms.ToTensor(),#轉為Tensor
? ? ? ? ? ? ? ? transforms.Normalize([0.485,0.456,0.406], [0.229,0.224,0.225])# 標準化
])
train_loader = torch.utils.data.DataLoader(
SVHNDataset(train_path, train_label, trans_fun),
batch_size=40,shuffle=True)# 批量大小40推沸,打亂順序
test_loader = torch.utils.data.DataLoader(
SVHNDataset(test_path, [], trans_fun),
batch_size=40,shuffle=False)
model = SVHN_Model1()
criterion = nn.CrossEntropyLoss()# 交叉熵損失函數(shù)
optimizer = torch.optim.Adam(model.parameters(),0.001)# Adam優(yōu)化器
use_cuda = torch.cuda.is_available()
if use_cuda: model = model.cuda()
for epochin range(10):
train_loss = train(train_loader, model, criterion, optimizer)# 訓練
? ? print(epoch, train_loss)
test_predict_label = predict(test_loader, model)
test_predict_label = np.vstack([
test_predict_label[:, :11].argmax(1), test_predict_label[:,11:22].argmax(1),
test_predict_label[:,22:33].argmax(1), test_predict_label[:,33:44].argmax(1),
test_predict_label[:,44:55].argmax(1),
]).T
test_label_pred = []
for xin test_predict_label:
test_label_pred.append(''.join(map(str, x[x!=10])))# 取出預字符不為10的字符且順序排列
df_submit = pd.read_csv('../input/sample_submit_A.csv')
df_submit['file_code'] = test_label_pred
df_submit.to_csv('submit.csv',index=None)# 保存結果文件