获得正确的张量大小
Get the right tensor size
我想要正确的张量大小,因为在 loss = criterion(out,target)
行中出现以下错误:
预期输入 batch_size (4200) 以匹配目标 batch_size (64)。
我该如何解决挑战?
我的输出张量具有大小 ([4200, 2]) 和我的目标张量 ([64,2])。
用例是图像 classification。有两个 class。我的批量大小是 64,图像的灰度大小为 180 x 115px。
请不要混淆:有一些 'break' 用于测试早期开发状态的代码。
我加载了四批,所以 256 张图像。
使用这种方法我将加载我的图像:
def dataPrep(list_of_data, data_path, category, quantity):
global train_data
target_list = []
train_data_list = []
transform = transforms.Compose([
transforms.ToTensor(),
])
len_data = len(train_data)
print('Len_data: ', len_data)
for item in list_of_data:
f = random.choice(list_of_data)
list_of_data.remove(f)
print(data_path + f)
try:
img = Image.open(data_path +f)
except:
continue
img_crop = img.crop((310,60,425,240))
img_tensor = transform(img_crop)
print(img_tensor.size())
train_data_list.append(img_tensor)
isPseudo = 0
isTrue = 1
if category == True:
target = [isPseudo,isTrue]
else:
isPseudo =1
isTrue = 0
target = [isPseudo, isTrue]
target_list.append(target)
if len(train_data_list) >=64:
train_data.append((torch.stack(train_data_list), target_list))
train_data_list = []
target_list = []
if (len_data*64 + quantity) <= len(train_data)*64:
break
print(len(train_data) *64)
return list_of_data
加载图像后,我创建模型和优化器。
model = net.Netz()
optimizer = optim.SGD(model.parameters(), lr= 0.1, momentum = 0.8)
我的 class 'Netz' 看起来像这样:
class Netz(nn.Module):
def __init__(self):
super(Netz, self).__init__()
self.conv1 = nn.Conv2d(1,10, kernel_size=5)
self.conv2 = nn.Conv2d(10,20, kernel_size = 5)
self.conv_dropout = nn.Dropout2d()
self.fc1 = nn.Linear(320,60)
self.fc2 = nn.Linear(60,2)
def forward(self,x):
x = self.conv1(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
x = self.conv2(x)
x = self.conv_dropout(x)
x = F.max_pool2d(x,2)
x = F.relu(x)
x = x.view(-1,320)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, -1)
最后我会训练我的CNN:
def trainM(epoch):
model.train()
batch_id = 0
for batch_id, (data, target) in enumerate(net.train_data):
#data = data.cuda()
#target = target.cuda()
target = torch.Tensor(target[64*batch_id:64*(batch_id+1)])
data = Variable(data)
target = Variable(target)
optimizer.zero_grad()
out = model(data)
criterion = F.nll_loss
print('Size of out:', out.size())
print('Size of target:', target.size())
loss = criterion(out,target)
loss.backward()
optimizer.step()
print('Tain Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch,batch_id*len(data), len(net.train_data.dataset), 100*batch_id/len(net.train_data), loss.item()))
batch_id += 1
break
for item in range(0,10):
trainM(item)
break
据我所知,您需要一条线来分割数据,就像您在训练循环中对目标所做的那样:
target = torch.Tensor(target[64*batch_id:64*(batch_id+1)])
data = torch.Tensor(data[64*batch_id:64*(batch_id+1)])
主要问题在 Netz x = x.view(-1,320)
你有 64 个批次 20 个通道 42 x 25 宽度和高度,如果你将它重塑为 -1,320 将得到 4200 x 320。
我可以建议 3 个可能的选项来保留批量大小;
(一般的做法)将输入填充成正方形,更新卷积部分,使其在FC层之前的输出通道数多,高宽数少。例如获取 x.shape = (batchsize, 128,2,2)
然后获取 fc1 = Linear(512, 60)
并在此之前获取 x = x.reshape(x.shape[0], -1)
。 (这里在应用 fc1
之前你可以做一个 1x1 卷积)。
使卷积结束时的通道数为 1,即得到类似 x.shape = (batchsize,1,42,25)
的内容,然后相应地采用 fc1
。
dox=reshape(*x.shape[:2], -1)
换句话说,同时保留 chanel 和 batchsize。添加另一个 FC 层 fc_e = Linear(20,1)
以压缩您的频道。
class Netz(nn.Module):
def __init__(self):
super(Netz, self).__init__()
self.conv1 = nn.Conv2d(1,10, kernel_size=5)
self.conv2 = nn.Conv2d(10,20, kernel_size = 5)
self.conv_dropout = nn.Dropout2d()
self.fc1 = nn.Linear(1050,60)
self.fc2 = nn.Linear(60,2)
self.fce = nn.Linear(20,1)
def forward(self,x):
x = self.conv1(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
x = self.conv2(x)
x = self.conv_dropout(x)
x = F.max_pool2d(x,2)
x = F.relu(x)
x = x.reshape(x.shape[0],x.shape[1], -1)
x = F.relu(self.fc1(x))
x = self.fc2(x)
x = self.fce(x.permute(0,2,1)).squeeze(-1)
return F.log_softmax(x, -1)
请记住,您需要在要表示的信息量(应该很高)和线性层的输入数量(不是那么高)之间进行权衡。最后,这取决于您选择如何解决该问题。第三个最接近你的解决方案,但我建议找出一个符合第一种方法的模型
我想要正确的张量大小,因为在 loss = criterion(out,target)
行中出现以下错误:
预期输入 batch_size (4200) 以匹配目标 batch_size (64)。
我该如何解决挑战?
我的输出张量具有大小 ([4200, 2]) 和我的目标张量 ([64,2])。 用例是图像 classification。有两个 class。我的批量大小是 64,图像的灰度大小为 180 x 115px。 请不要混淆:有一些 'break' 用于测试早期开发状态的代码。 我加载了四批,所以 256 张图像。
使用这种方法我将加载我的图像:
def dataPrep(list_of_data, data_path, category, quantity):
global train_data
target_list = []
train_data_list = []
transform = transforms.Compose([
transforms.ToTensor(),
])
len_data = len(train_data)
print('Len_data: ', len_data)
for item in list_of_data:
f = random.choice(list_of_data)
list_of_data.remove(f)
print(data_path + f)
try:
img = Image.open(data_path +f)
except:
continue
img_crop = img.crop((310,60,425,240))
img_tensor = transform(img_crop)
print(img_tensor.size())
train_data_list.append(img_tensor)
isPseudo = 0
isTrue = 1
if category == True:
target = [isPseudo,isTrue]
else:
isPseudo =1
isTrue = 0
target = [isPseudo, isTrue]
target_list.append(target)
if len(train_data_list) >=64:
train_data.append((torch.stack(train_data_list), target_list))
train_data_list = []
target_list = []
if (len_data*64 + quantity) <= len(train_data)*64:
break
print(len(train_data) *64)
return list_of_data
加载图像后,我创建模型和优化器。
model = net.Netz()
optimizer = optim.SGD(model.parameters(), lr= 0.1, momentum = 0.8)
我的 class 'Netz' 看起来像这样:
class Netz(nn.Module):
def __init__(self):
super(Netz, self).__init__()
self.conv1 = nn.Conv2d(1,10, kernel_size=5)
self.conv2 = nn.Conv2d(10,20, kernel_size = 5)
self.conv_dropout = nn.Dropout2d()
self.fc1 = nn.Linear(320,60)
self.fc2 = nn.Linear(60,2)
def forward(self,x):
x = self.conv1(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
x = self.conv2(x)
x = self.conv_dropout(x)
x = F.max_pool2d(x,2)
x = F.relu(x)
x = x.view(-1,320)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, -1)
最后我会训练我的CNN:
def trainM(epoch):
model.train()
batch_id = 0
for batch_id, (data, target) in enumerate(net.train_data):
#data = data.cuda()
#target = target.cuda()
target = torch.Tensor(target[64*batch_id:64*(batch_id+1)])
data = Variable(data)
target = Variable(target)
optimizer.zero_grad()
out = model(data)
criterion = F.nll_loss
print('Size of out:', out.size())
print('Size of target:', target.size())
loss = criterion(out,target)
loss.backward()
optimizer.step()
print('Tain Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch,batch_id*len(data), len(net.train_data.dataset), 100*batch_id/len(net.train_data), loss.item()))
batch_id += 1
break
for item in range(0,10):
trainM(item)
break
据我所知,您需要一条线来分割数据,就像您在训练循环中对目标所做的那样:
target = torch.Tensor(target[64*batch_id:64*(batch_id+1)])
data = torch.Tensor(data[64*batch_id:64*(batch_id+1)])
主要问题在 Netz x = x.view(-1,320)
你有 64 个批次 20 个通道 42 x 25 宽度和高度,如果你将它重塑为 -1,320 将得到 4200 x 320。
我可以建议 3 个可能的选项来保留批量大小;
(一般的做法)将输入填充成正方形,更新卷积部分,使其在FC层之前的输出通道数多,高宽数少。例如获取
x.shape = (batchsize, 128,2,2)
然后获取fc1 = Linear(512, 60)
并在此之前获取x = x.reshape(x.shape[0], -1)
。 (这里在应用fc1
之前你可以做一个 1x1 卷积)。使卷积结束时的通道数为 1,即得到类似
x.shape = (batchsize,1,42,25)
的内容,然后相应地采用fc1
。do
x=reshape(*x.shape[:2], -1)
换句话说,同时保留 chanel 和 batchsize。添加另一个 FC 层fc_e = Linear(20,1)
以压缩您的频道。
class Netz(nn.Module):
def __init__(self):
super(Netz, self).__init__()
self.conv1 = nn.Conv2d(1,10, kernel_size=5)
self.conv2 = nn.Conv2d(10,20, kernel_size = 5)
self.conv_dropout = nn.Dropout2d()
self.fc1 = nn.Linear(1050,60)
self.fc2 = nn.Linear(60,2)
self.fce = nn.Linear(20,1)
def forward(self,x):
x = self.conv1(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
x = self.conv2(x)
x = self.conv_dropout(x)
x = F.max_pool2d(x,2)
x = F.relu(x)
x = x.reshape(x.shape[0],x.shape[1], -1)
x = F.relu(self.fc1(x))
x = self.fc2(x)
x = self.fce(x.permute(0,2,1)).squeeze(-1)
return F.log_softmax(x, -1)
请记住,您需要在要表示的信息量(应该很高)和线性层的输入数量(不是那么高)之间进行权衡。最后,这取决于您选择如何解决该问题。第三个最接近你的解决方案,但我建议找出一个符合第一种方法的模型