Построение потокобезопасного генератора для кераса для использования несколькими рабочими - PullRequest
0 голосов
/ 02 марта 2020

Если у кого-то есть опыт создания поточно-безопасных генераторов, есть ли способ сделать это с помощью генератора функций? Я сталкивался с этим постом по адресу: https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly, и я пытался основать свой код на этом посте, но я получаю сообщение об ошибке, которое на самом деле не имеет смысла, есть ли у кого-нибудь понимание?

import numpy as np
import keras
import cv2
import os
from depth_functional import predict

class data_generator(keras.utils.Sequence):

    def __init__(self,ImgPath,string_ids,keys,bs,model,bboxes):
        'Initialize'
        self.ImgPath=ImgPath
        self.string_ids=string_ids
        self.keys=keys
        self.bs=bs
        self.model=model
        self.bboxes=bboxes

        #will keep track how many times we have pulled batches of data
        self.count=0
    def __len__(self):
        #Denotes Number of batches per epoch
        return (int(np.floor(len(self.list_IDs))/self.bs))

    def __getitem__(self,index):
        #Generate index of the batch
        indexes=self.indexes[index*self.bs:(index+1)*self.bs]

        #find a list of ids you want to generate
        string_ids_temp=[self.string_ids[k] for k in indexes]

        #Generate data
        RGBD,Masks=self.__data_generation(string_ids_temp)

        return RGBD,Masks

    def on_epoch_end(self):
        self.indexes=np.arange(len(self.string_ids))

    def __data_generation(self,string_ids_temp):
        os.chdir('C:\\Users\\'+self.ImgPath)
        RGBD_images=np.zeros((self.bs,240,320))
        Masks=np.zeros((self.bs,240,320,19))

        for i in range(len(string_ids_temp)):
            img=cv2.imread(string_ids_temp[i] +'.jpg')
            RGBD,masks=self.ProcessData(img,self.bboxes[self.count],self.keys[self.count])
            RGBD_images[i,:,:,:]=RGBD
            Masks[i,:,:,:]=masks
            if self.count >= len(self.keys):
                self.count=0


    def ProcessData(self,img,bbox,keys):
        zeros=np.zeros((img.shape[0],img.shape[1],18))
        mask=np.zeros((240,320,19))

        bbox_height=abs(bbox[0]-bbox[2])
        bbox_width=abs(bbox[1]-bbox[3])
        sigma_x=400*(bbox_width/224)
        sigma_y=400*(bbox_height/224)

        for part in range(18):
            if keys[part][2]==2:
                for j in range(img.shape[1]):
                    x=np.linspace(0,img.shape[0]-1,img.shape[0])
                    y=np.full((img.shape[0],),float(j))
                    x_key=np.full((img.shape[0],),keys[part][1])
                    y_key=np.full((img.shape[0],),keys[part][0])

                    zeros[:,j,part]=np.exp(-(np.square(x-x_key)/sigma_x+np.square(y-y_key)/sigma_y))

        zeros=cv2.resize(zeros,(320,240))

        mask[:,:,18]=np.amax(mask,axis=-1)

        resized_img=cv2.resize(img,(640,480))/255.0
        depth=predict(self.model,resized_img)[0]
        depth=depth/np.amax(depth)

        smaller_img=cv2.resize(img,(320,240))/255.0

        RGBD = np.concatenate((smaller_img,depth),axis=-1)

        return RGBD,mask

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

  File "C:\Users\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
    execfile(filename, namespace)

  File "C:\Users\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:\Users\Anaconda3\lib\site-packages\tensorflow_core\python\keras\engine\training.py", line 1297, in fit_generator
    steps_name='steps_per_epoch')

  File "C:\Users\Anaconda3\lib\site-packages\tensorflow_core\python\keras\engine\training_generator.py", line 144, in model_iteration
    shuffle=shuffle)

  File "C:\Users\Anaconda3\lib\site-packages\tensorflow_core\python\keras\engine\training_generator.py", line 477, in convert_to_generator_like
    num_samples = int(nest.flatten(data)[0].shape[0])

AttributeError: 'data_generator' object has no attribute 'shape'

Редактировать следующий скелет TheLoneDeranger:

class Generator():

    def __init__(self,ImgPath,string_ids,keys,bboxes,bs,model):

        self.ImgPath=ImgPath
        self.string_ids=string_ids
        self.keys=keys
        self.bboxes=bboxes
        self.bs=bs
        self.model=model

        #Will count how many data samples we have pulled
        self.count=0

        def __iter__(self):
            return self

        def __len__(self):
            #returns the total number of training samples
            return len(self.keys) 

        def __next__(self):
            RGBD_Images=np.zeros((self.bs,240,320,4))
            Masks=np.zeros((self.bs,240,320,19))

            os.chdir('C:\\Users\\'+ImgPath)

            for i in range(self.count*self.bs,(self.count+1)*self.bs):
                img=cv2.imread(self.string_ids[i]+'.jpg')
                zeros=np.zeros((img.shape[0],img.shape[1],18),dtype='float')
                mask=np.zeros((240,320,19),dtype='float')

                bbox_height = abs(self.bboxes[i][0]-self.bboxes[i][2])
                bbox_width = abs(self.bboxes[i][1]-self.bboxes[i][3])
                sigma_x=400*(bbox_width/224)
                sigma_y=400*(bbox_height/224)

                for part in range(18):
                    if self.keys[i][part][2]==2:
                        for j in range(img.shape[1]):
                            x = np.linspace(0,img.shape[0]-1,img.shape[0])
                            y = np.full((img.shape[0],),float(j))
                            x_key = np.full((img.shape[0],),self.keys[i][part][1])
                            y_key = np.full((img.shape[0],),self.keys[i][part][0])

                            zeros[:,j,part]=np.exp(-(np.square(x-x_key)/sigma_x+np.square(y-y_key)/sigma_y))

                zeros=cv2.resize(zeros,(320,240))
                mask[:,:,18]=np.amax(mask,axis=-1)
                Masks[i%self.bs,:,:,:]=mask

                resized_img = cv2.resize(img,(640,480))/255.0
                depth = predict(self.model,resized_img)[0]    #240 x 320 x1 output
                depth=depth/np.amax(depth)

                smaller_img = cv2.resize(img,(320,240))/255.0

                RGBD = np.concatenate((smaller_img,depth),axis=2)
                RGBD_Images[i%self.bs,:,:,:]=RGBD


            self.count+=1
            if (self.count+1)*self.bs >= len(self.keys):
                self.count=0

            return (RGBD_Images,Masks)

1 Ответ

1 голос
/ 02 марта 2020

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

class Generator:
  def __init__(self,base_path):
    # initialize however... for example:
    self.base_path = base_path
    self.files = os.listdir(self.base_path)

  def __iter__(self):
    return self

  def __len__(self):
    return len(self.files) # needs to return total training samples

  def __next__(self):
    # get your images and labels
    return (images,labels)

Затем вы можете использовать их так:

train_gen = Generator(train_path)
val_gen = Generator(val_path)
model.fit_generator(train_gen,
                    validation_data=val_gen,
                    steps_per_epoch=200,
                    validation_steps=200,
                    epochs=666)

Надеюсь, что поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...