ニューラルネットワークをトレーニングするために、YouTubeで見つけたコードを変更しました。次のようになります。
def data_generator(samples, batch_size, shuffle_data = True, resize=224):
num_samples = len(samples)
while True:
random.shuffle(samples)
for offset in range(0, num_samples, batch_size):
batch_samples = samples[offset: offset + batch_size]
X_train = []
y_train = []
for batch_sample in batch_samples:
img_name = batch_sample[0]
label = batch_sample[1]
img = cv2.imread(os.path.join(root_dir, img_name))
#img, label = preprocessing(img, label, new_height=224, new_width=224, num_classes=37)
img = preprocessing(img, new_height=224, new_width=224)
label = my_onehot_encoded(label)
X_train.append(img)
y_train.append(label)
X_train = np.array(X_train)
y_train = np.array(y_train)
yield X_train, y_train
今、私はこのコードを使用してニューラルネットワークをトレーニングしようとしました。トレーニングサンプルサイズは105.000です(37の可能性のうち8文字、A〜Z、0〜9、および空白スペースを含む画像ファイル)。比較的小さいバッチサイズ(32、それはすでに小さすぎると思います)を使用してより効率的にしましたが、それでも最初のエポックの4分の1をトレーニングするのに永遠のようにかかりました(エポックごとに826ステップあり、90分かかりました) 199ステップ... steps_per_Epoch = num_train_samples // batch_size
)。
データジェネレーターには次の関数が含まれています。
def shuffle_data(data):
data=random.shuffle(data)
return data
この関数をもっと効率的にしたり、ジェネレータから除外したりすることはできないと思います。
def preprocessing(img, new_height, new_width):
img = cv2.resize(img,(new_height, new_width))
img = img/255
return img
データを前処理/サイズ変更するために、私はこのコードを使用して画像を一意のサイズにします。 (224、224、3)。ジェネレーターのこの部分は最も時間がかかると思いますが、ジェネレーターから除外する可能性はありません(バッチの外でイメージのサイズを変更すると、メモリがいっぱいになるため)。
#One Hot Encoding of the Labels
from numpy import argmax
# define input string
def my_onehot_encoded(label):
# define universe of possible input values
characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ '
# define a mapping of chars to integers
char_to_int = dict((c, i) for i, c in enumerate(characters))
int_to_char = dict((i, c) for i, c in enumerate(characters))
# integer encode input data
integer_encoded = [char_to_int[char] for char in label]
# one hot encode
onehot_encoded = list()
for value in integer_encoded:
character = [0 for _ in range(len(characters))]
character[value] = 1
onehot_encoded.append(character)
return onehot_encoded
この部分には、より効率的な方法が1つあると思います。このコードをジェネレーターから除外し、ジェネレーターの外に配列y_trainを生成することを考えています。これにより、ジェネレーターは毎回ラベルをホットエンコードする必要がなくなります。
どう思いますか?それとも、まったく異なるアプローチを取るべきでしょうか?
手がかりしか与えられていないので、あなたの質問は非常に興味深く感じました。これが私の調査です。
あなたのスニペットを使用して、私は GitHubリポジトリ およびPythonでジェネレーター関数を使用することの主に 利点について に焦点を当てたYouTubeの3部のビデオチュートリアルを見つけました。データは this kaggle に基づいています(別のCNNネットワークですでに試したアプローチと比較して、使用中のAPIを確認するために、その問題についてさまざまなカーネルを確認することをお勧めします)。
難しくはありませんが、データジェネレータを最初から作成する必要はありませんが、ホイールを発明しても生産的ではありません。
tf.data.Dataset
とともに提供します。それにもかかわらず、カグルのタスクを解決するために、モデルは単一の画像のみを認識する必要があるため、モデルは単純なディープCNNです。しかし、私が理解しているように、8つのランダムな文字(クラス)を1つの画像に組み合わせて、一度に 複数のクラスを認識 にします。そのためには、モデルとしてR-CNNまたはYOLOが必要です。私は最近自分のためにオープンしました YOLO v4 、そして特定のタスクでそれを非常に迅速に動作させることが可能です。
デザインとコードに関する一般的なアドバイス。