簡體   English   中英

如何微調 EfficientNetB3 model 並保留其一些現有標簽?

[英]How can I fine-tune EfficientNetB3 model and retain some of its exisiting labels?

我已經在我的大型圖像集上測試了 EfficientNetB3 model(在 ImageNet 上訓練過),它可以識別我擁有的某些類別的圖像,准確度各不相同,而其他類別則根本無法識別。

例如,它在校車方面做得很好: ('n04146614', 'school_bus')('n04487081', 'trolleybus') , ('n02701002', 'ambulance') , ('n03977966', 'police_van')

所以我想保留這些標簽並向 model 提供更多圖像以提高其檢測率。 同時,雖然它檢測到警車,但它完全忽略了其他警車,因此我必須為它們創建新標簽。

我應該如何處理? 這可能在一次培訓 session 中實現嗎?

使用在 ima.net 上訓練的 model 可以很好地識別包含在原始 imag.net 數據集中的圖像。 如果它們不以 class 的形式存在,則 model 的性能會很差。 您通常做的是為數據集中的唯一類自定義 model。 這個過程稱為遷移學習。 首先,您必須決定要上什么課,並收集與每個 class 相關的適當圖像。例如,假設您有警車、校車、消防車、垃圾車和送貨車等課程。 因此,您需要為每個 class 收集適當的圖像。通常,每個 class 至少需要大約 120 到 150 張圖像。 所以我們現在有 5 個類。 創建單個目錄調用的是sdir。 在 sdir 下面創建 5 個子目錄,每個 class。將這些命名為警車、校車等。現在將圖像放入各自的子目錄中。 現在可以使用下面的 function 將數據集拆分為三個數據集,分別稱為 train_df、test_df 和 valid_df。

def preprocess (sdir, trsplit, vsplit):
    filepaths=[]
    labels=[]    
    classlist=os.listdir(sdir)
    for klass in classlist:
        classpath=os.path.join(sdir,klass)
        if os.path.isdir(classpath):
            flist=os.listdir(classpath)
            for f in flist:
                fpath=os.path.join(classpath,f)
                filepaths.append(fpath)
                labels.append(klass)
    Fseries=pd.Series(filepaths, name='filepaths')
    Lseries=pd.Series(labels, name='labels')
    df=pd.concat([Fseries, Lseries], axis=1)            
    dsplit=vsplit/(1-trsplit)
    strat=df['labels']
    train_df, dummy_df=train_test_split(df, train_size=trsplit, shuffle=True, random_state=123, stratify=strat)
    strat=dummy_df['labels']
    valid_df, test_df= train_test_split(dummy_df, train_size=dsplit, shuffle=True, random_state=123, stratify=strat)
    print('train_df length: ', len(train_df), '  test_df length: ',len(test_df), '  valid_df length: ', len(valid_df))
    print(list(train_df['labels'].value_counts()))
    return train_df, test_df, valid_df

現在撥打function

sdir=r'C:\sdir'
trsplit=.8 # percent of images to use for training
vsplit=.1 # percent of images to use for validation
train_df, test_df, valid_df= preprocess(sdir,trsplit, vsplit)

現在您需要使用 ImageDataGenerator.flow_from_dataframe 創建 3 個生成器。 文檔在這里

channels=3
batch_size=20 # set batch size based on model complexity and sie of images
img_shape=(img_size[0], img_size[1], channels)
# calculate test_batch_size and test_steps so that test_batch_size X test_steps = number of test images
# this ensures you go through the test set exactly once when doing predictions on the test set
length=len(test_df)
test_batch_size=sorted([int(length/n) for n in range(1,length+1) if length % n ==0 and length/n<=80],reverse=True)[0]  
test_steps=int(length/test_batch_size)
print ( 'test batch size: ' ,test_batch_size, '  test steps: ', test_steps)
trgen=ImageDataGenerator(horizontal_flip=True)
tvgen=ImageDataGenerator()
msg='                                                              for the train generator'
print(msg, '\r', end='') 
train_gen=trgen.flow_from_dataframe( train_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=True, batch_size=batch_size)
msg='                                                              for the test generator'
print(msg, '\r', end='') 
test_gen=tvgen.flow_from_dataframe( test_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=False, batch_size=test_batch_size)
msg='                                                             for the validation generator'
print(msg, '\r', end='')
valid_gen=tvgen.flow_from_dataframe( valid_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=True, batch_size=batch_size)
classes=list(train_gen.class_indices.keys())
class_count=len(classes)
train_steps=int(np.ceil(len(train_gen.labels)/batch_size))
labels=test_gen.labels

現在創建您的 model。建議的 model 如下所示,使用 EfficientNetB3

def make_model(img_img_size, class_count,lr=.001, trainable=True):
    img_shape=(img_size[0], img_size[1], 3)
    model_name='EfficientNetB3'
    base_model=tf.keras.applications.efficientnet.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max') 
    base_model.trainable=trainable
    x=base_model.output
    x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
    x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
                    bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
    x=Dropout(rate=.45, seed=123)(x)        
    output=Dense(class_count, activation='softmax')(x)
    model=Model(inputs=base_model.input, outputs=output)
    model.compile(Adamax(learning_rate=lr), loss='categorical_crossentropy', metrics=['accuracy']) 
    return model, base_model # return the base_model so the callback can control its training state

現在撥打function

model, base_model=make_model(img_size, class_count)

現在你可以訓練你的 model

history=model.fit(x=train_gen,  epochs=epochs, verbose=0, validation_data=valid_gen,
               validation_steps=None,  shuffle=False,  initial_epoch=0)

訓練后,您可以評估模型在測試集上的性能

loss, acc=model.evaluate(test_gen, steps=test_steps)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM