PyTorch 表情识别
VX:13225601016? ? ? ?獲取源碼和數據集
實驗環境:
硬件環境:CPU i7-6500U,GPU GTX950M
軟件環境:python3.7,torch 1.7.0+cu101
實驗步驟:
1.訓練
數據集
將訓練集文件夾train和驗證集文件夾val加入到我的訓練文件夾mytrain內。測試集文件夾test和我的訓練集文件夾mytrain在同一工作目錄下。如圖1。
圖1數據集
訓練集和驗證集數據加載
在訓練數據集下,每種表情的圖片均存儲在其標簽為目錄的文件夾下。在這里可以使用torchvision.datasets.ImageFolder()方法來加載這種組織方式的數據集。如圖2。驗證集組織形式同訓練集,數據加載方式相同。
圖2訓練集的組織形式
data_dir?=?'./mytrain'data_transforms?=?transforms.Compose([transforms.ToTensor(),transforms.Grayscale(num_output_channels=1)])#數據加載成tensor,加載灰度圖像train_dataset?=?torchvision.datasets.ImageFolder(root?=?os.path.join(data_dir,?'train'),?transform?=?data_transforms)val_dataset?=?torchvision.datasets.ImageFolder(root?=?os.path.join(data_dir,?'val'),?transform?=?data_transforms)train_dataloader?=?DataLoader(dataset=train_dataset,?batch_size=128,?shuffle=True)val_dataloader?=?DataLoader(dataset=val_dataset,?batch_size=128,?shuffle=True)卷積神經網絡的定義
使用卷積神經網絡對數據集進行訓練。卷積層分為三層,輸入圖像每一層均以3*3卷積核進行訓練,每次經過卷積操作后進行歸一化,通過激活函數后在進行下采樣。線性層將卷積層得到的輸出作為輸入,輸出向量的維度等于類別數目7。網絡結構如圖3。
圖3 網絡結構圖
#?參數初始化def?gaussian_weights_init(m):classname?=?m.__class__.__name__#?字符串查找find,找不到返回-1,不等-1即字符串中含有該字符if?classname.find('Conv')?!=?-1:m.weight.data.normal_(0.0,?0.04)class?CNN(nn.Module):#?初始化網絡結構def?__init__(self):super(CNN,?self).__init__()#?第一次卷積、池化self.conv1?=?nn.Sequential(nn.Conv2d(in_channels=1,?out_channels=64,?kernel_size=3,?stride=1,?padding=1),?#?卷積層nn.BatchNorm2d(num_features=64),?#?歸一化nn.RReLU(inplace=True),?#?激活函數nn.MaxPool2d(kernel_size=2,?stride=2),?#?最大值池化)#?第二次卷積、池化self.conv2?=?nn.Sequential(nn.Conv2d(in_channels=64,?out_channels=128,?kernel_size=3,?stride=1,?padding=1),nn.BatchNorm2d(num_features=128),nn.RReLU(inplace=True),nn.MaxPool2d(kernel_size=2,?stride=2),)#?第三次卷積、池化self.conv3?=?nn.Sequential(nn.Conv2d(in_channels=128,?out_channels=256,?kernel_size=3,?stride=1,?padding=1),nn.BatchNorm2d(num_features=256),nn.RReLU(inplace=True),nn.MaxPool2d(kernel_size=2,?stride=2),)#?參數初始化self.conv1.apply(gaussian_weights_init)self.conv2.apply(gaussian_weights_init)self.conv3.apply(gaussian_weights_init)#?全連接層self.fc?=?nn.Sequential(nn.Dropout(p=0.2),nn.Linear(in_features=256?*?6?*?6,?out_features=4096),nn.RReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(in_features=4096,?out_features=1024),nn.RReLU(inplace=True),nn.Linear(in_features=1024,?out_features=256),nn.RReLU(inplace=True),nn.Linear(in_features=256,?out_features=7),)#?前向傳播def?forward(self,?x):x?=?self.conv1(x)x?=?self.conv2(x)x?=?self.conv3(x)#?數據扁平化x?=?x.view(x.shape[0],?-1)y?=?self.fc(x)return?y網絡的訓練
訓練步驟一共有100個epoch。batch_size=512。損失函數使用交叉熵損失函數,使用Adam方法對學習率進行優化。每進行5個epoch,分別在訓練集和驗證集上進行驗證,將驗證集上正確率大于先前正確率的model進行存儲。
def?train(train_dataset,?val_dataset,?batch_size,?epochs,?learning_rate,?wt_decay):train_loader?=?DataLoader(dataset=train_dataset,?batch_size=batch_size,?shuffle=True)val_loader?=?DataLoader(dataset=val_dataset,?batch_size=batch_size,?shuffle=True)model?=?CNN().to(device)loss_function?=?nn.CrossEntropyLoss().to(device)optimizer?=?optim.Adam(model.parameters(),?lr=learning_rate,?weight_decay=wt_decay)#?scheduler?=?optim.lr_scheduler.StepLR(optimizer,?step_size=10,?gamma=0.8)max_acc?=?0for?epoch?in?range(epochs):loss_rate?=?0model.train()?#?模型訓練for?images,?labels?in?train_loader:images?=?images.to(device)labels?=?labels.to(device)optimizer.zero_grad()output?=?model.forward(images)loss_rate?=?loss_function(output,?labels)loss_rate.backward()optimizer.step()print('After?{}?epochs?,?the?loss_rate?is?:?'.format(epoch?+?1),?loss_rate.item())with?SummaryWriter(comment='mynet')?as?w:#tensorboard?--logdir?C:\Users\29290\Desktop\2020CV表情識別實驗\runsw.add_scalar('scalar/train',loss.item(),epoch+1)w.add_graph(net,inputs)if?epoch?%?5?==?0:model.eval()?#?模型評估acc_train?=?validate(model,?train_dataset,?batch_size)acc_val?=?validate(model,?val_dataset,?batch_size)print('After?{}?epochs?,?the?acc_train?is?:?'.format(epoch?+?1),?acc_train)print('After?{}?epochs?,?the?acc_val?is?:?'.format(epoch?+?1),?acc_val)if?acc_val?>?max_acc:max_acc?=?acc_valtorch.save(model.state_dict(),'model.pth')main函數
def?main():data_dir?=?'./mytrain'data_transforms?=?transforms.Compose([transforms.ToTensor(),transforms.Grayscale(num_output_channels=1)])train_dataset?=?torchvision.datasets.ImageFolder(root?=?os.path.join(data_dir,?'train'),?transform?=?data_transforms)val_dataset?=?torchvision.datasets.ImageFolder(root?=?os.path.join(data_dir,?'val'),?transform?=?data_transforms)train(train_dataset,?val_dataset,?batch_size?=?512,?epochs=150,?learning_rate=0.001,?wt_decay=0)2.測試
數據加載
測試集文件組織形式與訓練集,驗證集不同如圖4。因此需要自定義數據加載。
圖4 測試數據集
class?Dataset(data.Dataset):#?初始化def?__init__(self,?root,?transform):super(Dataset,?self).__init__()self.root?=?rootself.files?=?os.listdir(self.root)self.transform?=?transformdef?__getitem__(self,?index):#?獲取數據集樣本個數img?=?Image.open(os.path.join(self.root,self.files[index]))img?=?self.transform(img)return?imgdef?__len__(self):return?len(self.files)定義測試函數
def?test(model,?dataset,?batch_size):test_loader?=?data.DataLoader(dataset,?batch_size)predict?=?[]for?images?in?test_loader:images?=?images.to(device)pred?=?model.forward(images)pred?=?np.argmax(pred.data.cpu().numpy(),?axis=1)predict.extend(list(pred))return?predictmain函數
將預測值對應的label寫入prediction.csv。
def?main():data_dir?=?'./test'label_list?=?['angry',?'disgust',?'fear',?'happy',?'neutral',?'sad',?'surprise']data_transforms?=?transforms.Compose([transforms.Grayscale(num_output_channels=1),transforms.ToTensor()])test_dataset?=?Dataset(data_dir?,data_transforms)test_loader?=?torch.utils.data.DataLoader(test_dataset,batch_size=8)model?=?torch.load('model_MyNet.pkl')predict?=?test(model,?test_dataset,?128)predict_label?=?[label_list[i]?for?i?in?predict]image?=?list(os.listdir(data_dir))df?=?pd.DataFrame({'image':image,'lable':predict_label})df.to_csv('prediction.csv',?index=False)實驗結果:
實驗在訓練集上準確率可以達到99%,而在驗證集上只能達到57%。實驗將loss,train_acc,val_acc進行可視化,如圖5.
圖5 網絡損失和正確率曲線
import?numpy?as?npimport?matplotlib.pyplot?as?pltloss?=?np.load('loss.npy')epoch1?=?np.arange(len(loss))train_acc?=?np.load('train_acc.npy')val_acc?=?np.load('val_acc.npy')epoch2?=?5*np.arange(len(train_acc))plt.plot(epoch1,?loss,?label='loss')plt.plot(epoch2,?train_acc,?label='train_acc')plt.plot(epoch2,?val_acc,?label='val_acc')plt.xlabel('epoch')plt.ylabel('loss')plt.legend()plt.show()總結
以上是生活随笔為你收集整理的PyTorch 表情识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库设计-电话号码长度
- 下一篇: php图型分析插件,IMAGE缩略图插件