CNNは、RNNと組み合わせます
問題
数日前、その後の質問は、RNN導出し、コードを学び、一緒にRNNとCNNは、我々はCNNの機能により抽出され、また、シーケンスそれとして見ることができますすることができますか?答えはイエスです。
しかし、私は一般的に直接抽出された特徴は、可変長列を扱うのRNN良いが、それは言うことですので、配列のサイズが不明である、しかし、ああRNN訓練ほとんど意味を与えていると思うニューロン画像の一般的な特性の数与えられ、RNNに続く今回は、ネットワーク変数の長さの出力を可能にする構造を設計しない限り、正直な感覚であることを多くのことを言います。(私の考えでは、重みがマスクニューロンを学ぶ規則に従って神経細胞の一部を除外するために、道路の簡単な再設計され、その後、RNNやLSTMトレーニングに投げ込ま)
それを達成する方法
import torch
import torch.nn as nn
from torchsummary import summary
from torchvision import datasets,transforms
import torch.optim as optim
from tqdm import tqdm
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.feature_extractor = nn.Sequential(
nn.Conv2d(1,16,kernel_size = 3,stride=2),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.Conv2d(16,64,kernel_size = 3,stride=2),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(64,128,kernel_size = 3,stride=2),
nn.BatchNorm2d(128),
nn.ReLU(),
)
self.rnn = nn.RNN(128,256,2) # input_size,output_size,hidden_num
self.h0 = torch.zeros(2,32,256) # 层数 batchsize hidden_dim
self.predictor = nn.Linear(4*256,10)
def forward(self,x):
x = self.feature_extractor(x) # (-1,128,2,2),4个神经元,128维度
x,ht = self.rnn(x.view(4,-1,128),self.h0) # (h*w,batch_size,hidden_dim)
#self.h0 = ht
x = self.predictor(x.view(-1,256*4))
return x
if __name__ == "__main__":
model = Model()
#summary(model,(1,28,28),device = "cpu")
loss_fn = nn.CrossEntropyLoss()
train_dataset = datasets.MNIST(root="./data/",train = True,transform = transforms.ToTensor(),download = True)
test_dataset = datasets.MNIST(root="./data/",train = False,transform = transforms.ToTensor(),download = True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=32,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=128,
shuffle=False)
optimizer = optim.Adam(model.parameters(),lr = 1e-3)
print(len(train_loader))
for epoch in range(100):
epoch_loss = 0.
for x,target in train_loader:
#print(x.size())
y = model(x)
loss = loss_fn(y,target)
epoch_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("epoch : {} and loss is : {}".format(epoch +1,epoch_loss))
torch.save(model.state_dict(),"rnn_cnn.pth")
私は私の訓練が収束した後に上記のコードは、RNNの入力ニューロンの数を指定し、それをしなければならない固定長入力していることがわかります。
可変長の場合、それは最も長い配列のlenで指定する必要がありますので、私は本当に可変長ことができないので、それは、まだ配列のlenに各バッチを変更する方法はありません。だから、私にできることは、最大元の特徴に足を通して重い右の役割を学ぶあなたは所望の効果を達成できるように、この重量は、実際には、0-1重量です。
import torch
import torch.nn as nn
from torchsummary import summary
from torchvision import datasets,transforms
import torch.optim as optim
import torch.nn.functional as F
from tqdm import tqdm
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.feature_extractor = nn.Sequential(
nn.Conv2d(1,16,kernel_size = 3,stride=2),
nn.BatchNorm2d(16),
nn.ReLU6(),
nn.Conv2d(16,64,kernel_size = 3,stride=2),
nn.BatchNorm2d(64),
nn.ReLU6(),
nn.Conv2d(64,128,kernel_size = 3,stride=2),
nn.BatchNorm2d(128),
nn.ReLU6(),
)
self.attn = nn.Conv2d(128,1,kernel_size = 1)
self.rnn = nn.RNN(128,256,2) # input_size,output_size,hidden_num
self.h0 = torch.zeros(2,32,256) # 层数 batchsize hidden_dim
self.predictor = nn.Linear(4*256,10)
def forward(self,x):
x = self.feature_extractor(x) # (-1,128,2,2),4个神经元,128维度
attn = F.relu(self.attn(x)) # (-1,1,2,2) -> (-1,4)
x = x * attn
#print(x.size())
x,ht = self.rnn(x.view(4,-1,128),self.h0) # (h*w,batch_size,hidden_dim)
#self.h0 = ht
x = self.predictor(x.view(-1,256*4))
return x
if __name__ == "__main__":
model = Model()
#summary(model,(1,28,28),device = "cpu")
#exit()
loss_fn = nn.CrossEntropyLoss()
train_dataset = datasets.MNIST(root="./data/",train = True,transform = transforms.ToTensor(),download = True)
test_dataset = datasets.MNIST(root="./data/",train = False,transform = transforms.ToTensor(),download = True)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=32,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=128,
shuffle=False)
optimizer = optim.Adam(model.parameters(),lr = 1e-3)
print(len(train_loader))
for epoch in range(100):
epoch_loss = 0.
for x,target in train_loader:
#print(x.size())
y = model(x)
loss = loss_fn(y,target)
epoch_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("epoch : {} and loss is : {}".format(epoch +1,epoch_loss))
torch.save(model.state_dict(),"rnn_cnn.pth")
私は、少し前の収束より速く、後者を訓練しました。