Ошибка: _pickle.Ошибка PicklingError: не удается рассолить <function в 0x0000002F2175B048>: поиск атрибута в __main__ не удался

#python #deep-learning #torchvision

#python #глубокое обучение #torchvision

Вопрос:

Я пытаюсь запустить следующий код, который сообщал о хорошей работе с другими пользователями, но я обнаружил эту ошибку.

кодирование: utf-8 —

Импортируйте материал

 import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils import data
from torch.utils.data import DataLoader
import torchvision.transforms as transforms

import cv2

import numpy as np

import csv
  

Шаг 1: считывание из файла журнала

 samples = []
with open('data/driving_log.csv') as csvfile:
    reader = csv.reader(csvfile)
    next(reader, None)
    for line in reader:
        samples.append(line)
    
  

Шаг 2: разделите данные на обучающий набор и набор проверки

 train_len = int(0.8*len(samples))
valid_len = len(samples) - train_len
train_samples, validation_samples = data.random_split(samples, lengths=[train_len, valid_len])
  

Шаг 3a: определите процессы увеличения, преобразования, параметры и набор данных для dataloader

 def augment(imgName, angle):
  name = 'data/IMG/'   imgName.split('/')[-1]
  current_image = cv2.imread(name)
  current_image = current_image[65:-25, :, :]
  if np.random.rand() < 0.5:
    current_image = cv2.flip(current_image, 1)
    angle = angle * -1.0  
  return current_image, angle

class Dataset(data.Dataset):

    def __init__(self, samples, transform=None):

        self.samples = samples
        self.transform = transform

    def __getitem__(self, index):
      
        batch_samples = self.samples[index]
        
        steering_angle = float(batch_samples[3])
        
        center_img, steering_angle_center = augment(batch_samples[0], steering_angle)
        left_img, steering_angle_left = augment(batch_samples[1], steering_angle   0.4)
        right_img, steering_angle_right = augment(batch_samples[2], steering_angle - 0.4)

        center_img = self.transform(center_img)
        left_img = self.transform(left_img)
        right_img = self.transform(right_img)

        return (center_img, steering_angle_center), (left_img, steering_angle_left), (right_img, steering_angle_right)
      
    def __len__(self):
        return len(self.samples)
  

Шаг 3b: создание генератора с использованием загрузчика данных для распараллеливания процесса

 transformations = transforms.Compose([transforms.Lambda(lambda x: (x / 255.0) - 0.5)])

params = {'batch_size': 32,
          'shuffle': True,
          'num_workers': 4}

training_set = Dataset(train_samples, transformations)
training_generator = data.DataLoader(training_set, **params)

validation_set = Dataset(validation_samples, transformations)
validation_generator = data.DataLoader(validation_set, **params)
  

Step4: Define the network

class NetworkDense(nn.Module):

 def __init__(self):
    super(NetworkDense, self).__init__()
    self.conv_layers = nn.Sequential(
        nn.Conv2d(3, 24, 5, stride=2),
        nn.ELU(),
        nn.Conv2d(24, 36, 5, stride=2),
        nn.ELU(),
        nn.Conv2d(36, 48, 5, stride=2),
        nn.ELU(),
        nn.Conv2d(48, 64, 3),
        nn.ELU(),
        nn.Conv2d(64, 64, 3),
        nn.Dropout(0.25)
    )
    self.linear_layers = nn.Sequential(
        nn.Linear(in_features=64 * 2 * 33, out_features=100),
        nn.ELU(),
        nn.Linear(in_features=100, out_features=50),
        nn.ELU(),
        nn.Linear(in_features=50, out_features=10),
        nn.Linear(in_features=10, out_features=1)
    )
    
def forward(self, input):  
    input = input.view(input.size(0), 3, 70, 320)
    output = self.conv_layers(input)
    output = output.view(output.size(0), -1)
    output = self.linear_layers(output)
    return output


class NetworkLight(nn.Module):

def __init__(self):
    super(NetworkLight, self).__init__()
    self.conv_layers = nn.Sequential(
        nn.Conv2d(3, 24, 3, stride=2),
        nn.ELU(),
        nn.Conv2d(24, 48, 3, stride=2),
        nn.MaxPool2d(4, stride=4),
        nn.Dropout(p=0.25)
    )
    self.linear_layers = nn.Sequential(
        nn.Linear(in_features=48*4*19, out_features=50),
        nn.ELU(),
        nn.Linear(in_features=50, out_features=10),
        nn.Linear(in_features=10, out_features=1)
    )
    

def forward(self, input):
    input = input.view(input.size(0), 3, 70, 320)
    output = self.conv_layers(input)
    output = output.view(output.size(0), -1)
    output = self.linear_layers(output)
    return output
  

Step5: Define optimizer

 model = NetworkLight()
optimizer = optim.Adam(model.parameters(), lr=0.0001)

criterion = nn.MSELoss()
  

Step6: Check the device and define function to move tensors to that device

 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 
print('device is: ', device)

def toDevice(datas, device):
  
  imgs, angles = datas
  return imgs.float().to(device), angles.float().to(device)
  

Step7: Train and validate network based on maximum epochs defined

 max_epochs = 22

for epoch in range(max_epochs):
    
    model.to(device)
    
    # Training
    train_loss = 0
    model.train()
    for local_batch, (centers, lefts, rights) in enumerate(training_generator):
        # Transfer to GPU
        centers, lefts, rights = toDevice(centers, device), toDevice(lefts, device), toDevice(rights, device)
        
        # Model computations
        optimizer.zero_grad()
        datas = [centers, lefts, rights]        
        for data in datas:
            imgs, angles = data
#             print("training image: ", imgs.shape)
            outputs = model(imgs)
            loss = criterion(outputs, angles.unsqueeze(1))
            loss.backward()
            optimizer.step()

            train_loss  = loss.data[0].item()
            
        if local_batch % 100 == 0:
            print('Loss: %.3f '
                 % (train_loss/(local_batch 1)))

    
    # Validation
    model.eval()
    valid_loss = 0
    with torch.set_grad_enabled(False):
        for local_batch, (centers, lefts, rights) in enumerate(validation_generator):
            # Transfer to GPU
            centers, lefts, rights = toDevice(centers, device), toDevice(lefts, device), toDevice(rights, device)
        
            # Model computations
            optimizer.zero_grad()
            datas = [centers, lefts, rights]        
            for data in datas:
                imgs, angles = data
#                 print("Validation image: ", imgs.shape)
                outputs = model(imgs)
                loss = criterion(outputs, angles.unsqueeze(1))
                
                valid_loss  = loss.data[0].item()

            if local_batch % 100 == 0:
                print('Valid Loss: %.3f '
                     % (valid_loss/(local_batch 1)))
  

Шаг 8: определите состояние и сохраните запись модели в состояние

 state = {
        'model': model.module if device == 'cuda' else model,
        }

torch.save(state, 'model.h5')
  

это сообщение об ошибке:

 "D:VICOBack upvenvScriptspython.exe" "D:/VICO/Back up/venv/Scripts/self_driving_car.py"
device is:  cpu
Traceback (most recent call last):
  File "D:/VICO/Back up/venv/Scripts/self_driving_car.py", line 163, in <module>
    for local_batch, (centers, lefts, rights) in enumerate(training_generator):
  File "D:VICOBack upvenvlibsite-packagestorchutilsdatadataloader.py", line 291, in __iter__
    return _MultiProcessingDataLoaderIter(self)
  File "D:VICOBack upvenvlibsite-packagestorchutilsdatadataloader.py", line 737, in __init__
    w.start()
  File "C:UsersisonataAppDataLocalProgramsPythonPython37libmultiprocessingprocess.py", line 112, in start
    self._popen = self._Popen(self)
  File "C:UsersisonataAppDataLocalProgramsPythonPython37libmultiprocessingcontext.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:UsersisonataAppDataLocalProgramsPythonPython37libmultiprocessingcontext.py", line 322, in _Popen
    return Popen(process_obj)
  File "C:UsersisonataAppDataLocalProgramsPythonPython37libmultiprocessingpopen_spawn_win32.py", line 89, in __init__
    reduction.dump(process_obj, to_child)
  File "C:UsersisonataAppDataLocalProgramsPythonPython37libmultiprocessingreduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function <lambda> at 0x0000002F2175B048>: attribute lookup <lambda> on __main__ failed

Process finished with exit code 1
  

Я не уверен, что следующий шаг для решения проблемы.

Комментарии:

1. Использование state = {'model' : model.state_dict()} , за которым следует model.load_state_dict(...) при загрузке

Ответ №1:

pickle не удаляет объекты функций. Он ожидает найти объект функции, импортировав его модуль и просмотрев его имя. лямбды — это анонимные функции (без имени), поэтому это не работает. Решение состоит в том, чтобы назвать функцию на уровне модуля. Единственная лямбда, которую я нашел в вашем коде, это

 transformations = transforms.Compose([transforms.Lambda(lambda x: (x / 255.0) - 0.5)])
  

Предполагая, что это проблемная функция, вы можете

 def _my_normalization(x):
    return x/255.0 - 0.5

transformations = transforms.Compose([transforms.Lambda(_my_normalization])
  

У вас могут быть другие проблемы, потому что похоже, что вы выполняете работу на уровне модуля. Если это многопроцессорная обработка, и вы работаете в Windows, новый процесс импортирует файл и снова запустит весь этот код на уровне модуля. Это не проблема в linux / mac, где разветвленный процесс уже имеет модули, загруженные из родительского.

Комментарии:

1. Да, на самом деле у меня другая проблема с многопроцессорной обработкой.»Ошибка времени выполнения: была предпринята попытка запустить новый процесс до того, как текущий процесс завершил фазу начальной загрузки. Вероятно, это означает, что вы не используете fork для запуска дочерних процессов, и вы забыли использовать правильную идиому в главном модуле: if name == ‘ main ‘: freeze_support() … Строка «freeze_support()» может быть опущена, если программа не будет заморожена для создания исполняемого файла.

2. Привет, tdelaney, есть идеи по решению этой проблемы? Спасибо

3. Похоже, вы работаете в Windows. В Windows модули повторно импортируются в дочерние процессы. Все, что выполняется на уровне модуля, выполняется в дочернем элементе, в вашем случае это включает код, который создает подпроцессы, что приводит к бесконечному порождению процессов. Используйте if __name__ == "__main__": в своем основном скрипте. Просто найдите «Ошибка времени выполнения: была предпринята попытка запустить новый процесс», и вы получите сотню обращений.

4. Спасибо tdelaney, я ввел if name == » main «: и main() на шаге 7, и все работает хорошо.