[202国民大学冬季人工知能講座]第4週第3日学習内容


この授業ではPyTorchを用いてMNISTについて述べた.MNISTは基本的な深さ学習データセットであり,1から9まで異なるフォントの数字を学習することによって数字を学習し識別する.手書き分類深さ学習モード.
ここで使用するPyTorchモジュールを見てみましょう.
まず、PyTorchを読み込むにはtorchを入れる必要があります.
-> import torch
そしてニューラルネットワークTORCHを使うためにnnを読み込む必要があります.nnを簡単に入力することで,ニューラルネットワークを用いることができる.
-> import torch.nn as nn
最適化関数を使用してみます.だから懐中電灯でoptimを読み込み、optimを入力して最適化機能を使用できるようにすればよい.
-> import torch.optim as optim
最後はトーチnnは多様な機能を提供している.協調、解放、非線形活性化関数などがあります.
-> import torch.nn.functional as F
ここでは、データセットをロードする必要があり、画像を変換する必要があるため、torchvisionというモジュールを使用します.モジュールからデータセットと変換をロードします.
-> from torchvision import datasets, transforms
深度学習モデルを作成して使用する前に、CPUを使用するデバイス(device)が必要です.
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
MNISTを学習するためにtorchvisionからのパケットの1つであるデータセットのMNISTパケットをデータセットに設定する.MNISTを使用して学習データセットとテストデータセットをそれぞれ読み込みます.
train_dataset = datasets.MNIST(root='./mnist_data/', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./mnist_data/', train=False, transform=transforms.ToTensor())
TORCHutils.data.DataLoader()を使用してバッチ・サイズを決定できます.
ここでbatchは、所与のサイズに等しいデータ量を格納するデータの集合である.一度に大量のデータを勉強すると負荷がかかりすぎる可能性があるので、グループに分けて勉強します.人は試験などの勉強をするとき、一度にすべての内容をマスターしたいと思ったら、頭が痛くなります.そのため、科目を分けたり、時間を分けて勉強したりします.パソコンもそうです.
ここで、構成サイズは64に設定されている.
batch_size = 64
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
そして、学習するMNIST画像の画素サイズは784であり、480に縮小した後、200,80の順に縮小し、このサイズ80の画像を10個に分類する.各プロシージャでは、アクティブな関数RELUを使用して、0未満の値はすべて省略され、続行されます.したがって、モデルは次のように記述できます.
class Net(nn.Module):
	def __init__(self):
    	super(Net, self).__init__()
    	self.l1 = nn.Linear(784, 480)  # 입력 크기: 784 차원(픽셀)
    	self.l2 = nn.Linear(480, 200)
    	self.l3 = nn.Linear(200, 80)
    	self.l4 = nn.Linear(80, 10)  # 10개로 분류 (출력층)

	def forward(self, x):
    	x = x.view(-1, 784)  # (배치 사이즈, 1, 28, 28) 크기의 데이터를 (배치 사이즈, 784) 형태로 변경
    	x = F.relu(self.l1(x))
    	x = F.relu(self.l2(x))
    	x = F.relu(self.l3(x))
    	return self.l4(x)
モデル名はNetに設定されています.
ただし、このモデルを使用するにはデバイス(device)が必要なため、使用するモデルクラスオブジェクトです.to()関数でデバイスを有効にします.
model = Net().to(device)
このように学習モデルさえ設定すれば,損失関数(loss function)と最適化(optimization)が必要となる.
答えを10個のカテゴリに分けることにした以上,カテゴリを複数のカテゴリに分ける必要がある.このとき損失関数はクロスエントロピーを利用する.
criterion = nn.CrossEntropyLoss()
最適化はSGDを使用することを試みる.損失関数を複数回高速に計算するためらしい.
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.2)
運動量は0より大きい誤りであり,適切な方向にGDを加速させ,揺れ(振動)を低減できるパラメータである.
モデルを訓練し,学習するデータと正解データを分類する.モデルにデータを入力し、得られた仮定を出力という変数を生成することによって格納し、実際の値ground真値をtargetという変数に格納し、損失関数で両者を比較する.もちろん,損失を低減するためには逆伝搬を行い,その後最適化を行う必要がある.
def train(epoch):
	model.train()  # 모델을 학습 모드로 변환
	for batch_idx, (data, target) in enumerate(train_loader):
    	data, target = data.to(device), target.to(device)  # 각 data와 target을 앞서device에 보내는 것
    	optimizer.zero_grad()  # 각 학습마다 새 기울기를 계산하기 위해 0으로 초기화
    	output = model(data)  # data를 모델에 넣어서 가설(hypothesis) 얻기
    	loss = criterion(output, target)  # 가설인 output과 groundtruth인 target을 비교해서 loss계산
    	loss.backward()  # 역전파 알고리즘으로 loss계산
    	optimizer.step()  # 모델 가중치 업데이트
    	if batch_idx % 100 == 0:
        	print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.8f}'.format(
            epoch, batch_idx * len(data), len(train_loader.dataset),
            100. * batch_idx / len(train_loader), loss.data))
loss += criterion(output, target).data.item()
  • .item():二重引用符
  • pred = output.data.max(1, keepdim=True)[1]
  • 仮定出力の最大値を取得したmax()関数では、1は、出力の最大値が値とインデックスである方向に最大値を検索するかを示す.ここで必要なのはラベル(label)で、ここではインデックスに対応し、[1]を入力して2番目の要素を読み込みます.
  • correct += pred.eq(target.data.view_as(pred)).cpu().sum()
  • pred変数で予測される値が正しい可能性が高い場合、その正確な変数の値がますます高くなるにつれて、最終的な精度が向上する.
  • def test():
    	model.eval()
    	loss = 0
    	correct = 0
    	for data, target in test_loader:
        	data, target = data.to(device), target.to(device)
        	output = model(data)
        	loss += criterion(output, target).data.item()
        	pred = output.data.max(1, keepdim=True)[1]
        	correct += pred.eq(target.data.view_as(pred)).cpu().sum()
    	loss /= len(test_loader.dataset)
    	print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset)))
    結果
    Test set: Average loss: 0.0024, Accuracy: 9556/10000 (96%)
    for epoch in range(1, 11):
    	train(epoch)
    	test()
    関数の訓練とテストは1から10まで10回勉強します.
    image_data = test_dataset[0][0].to(device)
    image_label = test_dataset[0][1]
    print('숫자 이미지 X의 크기:', image_data.size())
    print('숫자 이미지 X의 레이블:', image_label)
    print(model(image_data))
    前述したように、該当数値の画像データとラベルを出力し、そのデータのTenser構造を確認する.