Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 自定义生成器以Keras为单位在数组输入中生成批量大小_Python_Tensorflow_Keras_Deep Learning_Neural Network - Fatal编程技术网

Python 自定义生成器以Keras为单位在数组输入中生成批量大小

Python 自定义生成器以Keras为单位在数组输入中生成批量大小,python,tensorflow,keras,deep-learning,neural-network,Python,Tensorflow,Keras,Deep Learning,Neural Network,我正在尝试使用一个自定义图像数据生成器,它将n个帧数组(来自视频)堆叠为每个输入的序列 我在这里找到了代码: 代码如下: import cv2 as cv import os import glob import numpy as np import random from tensorflow import keras import keras.preprocessing.image from tensorflow.python.keras.utils.data_utils import S

我正在尝试使用一个自定义图像数据生成器,它将n个帧数组(来自视频)堆叠为每个输入的序列

我在这里找到了代码:

代码如下:

import cv2 as cv
import os
import glob
import numpy as np
import random
from tensorflow import keras
import keras.preprocessing.image
from tensorflow.python.keras.utils.data_utils import Sequence

class VideoFrameGenerator(Sequence):
    
    def __init__(self,
                 rescale=1/255.,
                 nbframe:int=5,
                 classes:list=[],
                 batch_size:int=16,
                 use_frame_cache:bool=False,
                 target_shape:tuple=(224, 224),
                 shuffle:bool=True,
                 transformation:keras.preprocessing.image.ImageDataGenerator=None,
                 split:float=None,
                 nb_channel:int=3,
                 glob_pattern:str='./videos/{classname}/*.avi',
                 _validation_data:list=None):
        """ Create a generator that return batches of frames from video
        - nbframe: int, number of frame to return for each sequence
        - classes: list of str, classes to infer
        - batch_size: int, batch size for each loop
        - use_frame_cache: bool, use frame cache (may take a lot of memory for large dataset)
        - shape: tuple, target size of the frames
        - shuffle: bool, randomize files
        - transformation: ImageDataGenerator with transformations
        - split: float, factor to split files and validation
        - nb_channel: int, 1 or 3, to get grayscaled or RGB images
        - glob_pattern: string, directory path with '{classname}' inside that
            will be replaced by one of the class list
        - _validation_data: already filled list of data, do not touch !
            
        You may use the "classes" property to retrieve the class list afterward.
        
        The generator has that properties initialized:
        - classes_count: number of classes that the generator manages
        - files_count: number of video that the generator can provides
        - classes: the given class list
        - files: the full file list that the generator will use, this
            is usefull if you want to remove some files that should not be
            used by the generator.
        """
        
        # should be only RGB or Grayscale
        assert nb_channel in (1, 3)
        
        # we should have classes
        assert len(classes) > 0
        
        # shape size should be 2
        assert len(target_shape) == 2
        
        # split factor should be a propoer value
        if split is not None:
            assert split < 1.0 and split > 0.0

        # be sure that classes are well ordered
        classes.sort()
        
        self.rescale = rescale
        self.classes = classes
        self.batch_size = batch_size
        self.nbframe = nbframe
        self.shuffle = shuffle
        self.target_shape = target_shape
        self.nb_channel = nb_channel
        self.transformation = transformation
        self.use_frame_cache = use_frame_cache
        
        self._random_trans = []
        self.__frame_cache = {}
        self.files = []
        self.validation = []
        
        if _validation_data is not None:
            # we only need to set files here
            self.files = _validation_data
        else:
            if split is not None and split > 0.0:
                for c in classes:
                    files = glob.glob(glob_pattern.format(classname=c))
                    nbval = int(split * len(files))

                    print("class %s, validation count: %d" % (c, nbval))
                    
                    # generate validation indexes
                    indexes = np.arange(len(files))
                    
                    if shuffle:
                        np.random.shuffle(indexes)
                    
                    val = np.random.permutation(indexes)[:nbval]  # get some sample
                    indexes = np.array([i for i in indexes if i not in val]) # remove validation from train

                    # and now, make the file list
                    self.files += [files[i] for i in indexes]
                    self.validation += [files[i] for i in val]

            else:
                for c in classes:
                    self.files += glob.glob(glob_pattern.format(classname=c))

        # build indexes
        self.files_count = len(self.files)
        self.indexes = np.arange(self.files_count)
        self.classes_count = len(classes)
        
        self.on_epoch_end()  # to initialize transformations and shuffle indices
        
        print("get %d classes for %d files for %s" % (
            self.classes_count, 
            self.files_count,
            'train' if _validation_data is None else 'validation'))
            
    def get_validation_generator(self):
        """ Return the validation generator if you've provided split factor """
        return self.__class__(
            nbframe = self.nbframe,
            nb_channel=self.nb_channel,
            target_shape=self.target_shape,
            classes=self.classes,
            batch_size=self.batch_size,
            shuffle=self.shuffle,
            rescale=self.rescale,
            _validation_data=self.validation)
    
    def on_epoch_end(self):
        #prepare transformation to avoid __getitem__ to reinitialize them
        if self.transformation is not None:
            self._random_trans = []
            for i in range(self.files_count):
                self._random_trans.append(
                    self.transformation.get_random_transform(self.target_shape)
                )

        if self.shuffle:
            np.random.shuffle(self.indexes)
    
    def __len__(self):
        return int(np.floor(self.files_count / self.batch_size))
            
    def __getitem__(self, index):
        classes = self.classes
        shape = self.target_shape
        nbframe = self.nbframe
                
        labels = []
        images = []
        
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]

        t = None
            
        for i in indexes:
            # prepare a transformation if provided
            if self.transformation is not None:
                t = self._random_trans[i]
            
            # video = random.choice(files)
            video = self.files[i]
            cl = video.split(os.sep)[-2]

            # create a label array and set 1 to the right column
            
            label = np.zeros(len(classes))
            col = classes.index(int(cl))
            label[col] = 1.

            if video not in self.__frame_cache:
                cap = cv.VideoCapture(video)
                frames = []
                while True:
                    grabbed, frame = cap.read()
                    if not grabbed:
                        break        

                    # resize
                    frame = cv.resize(frame, shape)

                    # use RGB or Grayscale ?
                    if self.nb_channel == 3:
                        frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
                    else:
                        frame = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)

                    # to np
                    frame = keras.preprocessing.image.img_to_array(frame) * self.rescale

                    # keep frame
                    frames.append(frame)

                # Add 2 frames to drop first and last frame
                jump = len(frames)//(nbframe+2)

                # get only some images
                try:
                    frames = frames[jump::jump][:nbframe]
                    print(len(frames))

                except Exception as e:
                    print(video)
                    raise e
                
                # add to frame cache to not read from disk later
                if self.use_frame_cache:
                    self.__frame_cache[video] = frames
            else:
                frames = self.__frame_cache[video]

            # apply transformation
            if t is not None:
                frames = [self.transformation.apply_transform(frame, t) for frame in frames]
            
            # add the sequence in batch
            images.append(frames)
            labels.append(label)
                        
            
        return np.array(images), np.array(labels)
我用这个:

x = VideoFrameGenerator(
                 rescale=1/255.,
                 nbframe=10,
                 classes=list(range(0,14)),
                 batch_size=2,
                 use_frame_cache=False,
                 target_shape=(224, 224),
                 shuffle=True,
                 transformation=None,
                 split=.2,
                 nb_channel=3,
                 glob_pattern='../iemocap_data/label_split_videos/{classname}/*.mp4',
                 _validation_data=None
                       )
from keras.models import Sequential
from keras.layers import Dense, Conv2D

# define the keras model
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(224,224,3)))
model.add(Dense(8, activation='relu'))
model.add(Dense(14, activation='softmax'))
# compile the keras model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
# fit the keras model on the dataset
model.fit_generator(x,
                   steps_per_epoch=10,
                   )
我得到了这个错误:

Model: "sequential_51"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_16 (Conv2D)           (None, 222, 222, 32)      896       
_________________________________________________________________
dense_125 (Dense)            (None, 222, 222, 8)       264       
_________________________________________________________________
dense_126 (Dense)            (None, 222, 222, 14)      126       
=================================================================
Total params: 1,286
Trainable params: 1,286
Non-trainable params: 0
_________________________________________________________________
None
Epoch 1/1
10
10
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-164-29acc9e936f8> in <module>
     12 # fit the keras model on the dataset
     13 model.fit_generator(x,
---> 14                    steps_per_epoch=10,
     15                    )

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/legacy/interfaces.py in wrapper(*args, **kwargs)
     89                 warnings.warn('Update your `' + object_name + '` call to the ' +
     90                               'Keras 2 API: ' + signature, stacklevel=2)
---> 91             return func(*args, **kwargs)
     92         wrapper._original_function = func
     93         return wrapper

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/engine/training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
   1730             use_multiprocessing=use_multiprocessing,
   1731             shuffle=shuffle,
-> 1732             initial_epoch=initial_epoch)
   1733 
   1734     @interfaces.legacy_generator_methods_support

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/engine/training_generator.py in fit_generator(model, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
    218                                             sample_weight=sample_weight,
    219                                             class_weight=class_weight,
--> 220                                             reset_metrics=False)
    221 
    222                 outs = to_list(outs)

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/engine/training.py in train_on_batch(self, x, y, sample_weight, class_weight, reset_metrics)
   1506             x, y,
   1507             sample_weight=sample_weight,
-> 1508             class_weight=class_weight)
   1509         if self._uses_dynamic_learning_phase():
   1510             ins = x + y + sample_weights + [1]

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
    577             feed_input_shapes,
    578             check_batch_axis=False,  # Don't enforce the batch size.
--> 579             exception_prefix='input')
    580 
    581         if y is not None:

~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/engine/training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
    133                         ': expected ' + names[i] + ' to have ' +
    134                         str(len(shape)) + ' dimensions, but got array '
--> 135                         'with shape ' + str(data_shape))
    136                 if not check_batch_axis:
    137                     data_shape = data_shape[1:]

ValueError: Error when checking input: expected conv2d_16_input to have 4 dimensions, but got array with shape (2, 10, 224, 224, 3)

10
10
型号:“顺序_51”
_________________________________________________________________
层(类型)输出形状参数
=================================================================
conv2d_16(conv2d)(无、222、222、32)896
_________________________________________________________________
密集型_125(密集型)(无、222、222、8)264
_________________________________________________________________
密集型(密集型)(无、222、222、14)126
=================================================================
总参数:1286
可培训参数:1286
不可训练参数:0
_________________________________________________________________
没有一个
纪元1/1
10
10
---------------------------------------------------------------------------
ValueError回溯(最近一次调用上次)
在里面
12#在数据集上拟合keras模型
13型号。安装发电机(x,
--->每个历元14步=10,
15                    )
包装中的~/anaconda3/envs/tensorflow_2/lib/python3.7/site-packages/keras/legacy/interfaces.py(*args,**kwargs)
89 warnings.warn('Update your`'+object\u name+'`调用+
90'Keras 2 API:'+签名,堆栈级别=2)
--->91返回函数(*args,**kwargs)
92包装器._原始函数=func
93返回包装器
~/anaconda3/envs/tensorflow\u 2/lib/python3.7/site-packages/keras/engine/training.py-in-fit\u生成器(self、生成器、每个历元的步骤、历元、冗余、回调、验证数据、验证步骤、验证频率、类权重、最大队列大小、工作者、使用多处理、无序、初始历元)
1730使用多处理=使用多处理,
1731洗牌=洗牌,
->1732初始_历元=初始_历元)
1733
1734@interfaces.legacy\u生成器\u方法\u支持
~/anaconda3/envs/tensorflow\u 2/lib/python3.7/site-packages/keras/engine/training\u generator.py in-fit\u generator(模型、生成器、每个历元的步骤、历元、冗余、回调、验证数据、验证步骤、验证频率、类权重、最大队列大小、工人、使用多处理、无序、初始历元)
218样品重量=样品重量,
219级重量=级重量,
-->220重置(度量值=假)
221
222 outs=待办名单(outs)
~/anaconda3/envs/tensorflow\u 2/lib/python3.7/site-packages/keras/engine/training.py in train\u on\u on\u批次(自身、x、y、样本重量、等级重量、重置度量)
1506 x,y,
1507样品重量=样品重量,
->1508级重量=级重量)
1509如果self.\u使用\u动态\u学习\u阶段():
1510英寸=x+y+样本重量+[1]
~/anaconda3/envs/tensorflow\u 2/lib/python3.7/site-packages/keras/engine/training.py in\u-standard\u-user\u数据(自身、x、y、样本重量、类别重量、检查数组长度、批次大小)
577个进纸输入形状,
578检查_batch_axis=False,#不强制执行批大小。
-->579异常(前缀为“输入”)
580
581如果y不是无:
标准化输入数据中的~/anaconda3/envs/tensorflow\u 2/lib/python3.7/site-packages/keras/engine/training\u utils.py(数据、名称、形状、检查批处理轴、异常前缀)
133':应为“+名称[i]+”以具有”+
134 str(len(shape))+'维度,但得到数组'
-->135'带形状'+str(数据形状))
136如果不检查批次轴:
137数据形状=数据形状[1:]
ValueError:检查输入时出错:预期conv2d_16_输入有4个维度,但得到了形状为(2,10,224,224,3)的数组
10
10
发生什么事了?为什么batchsize是数组的第一个元素,为什么不接受它作为输入