物体检测中的不平衡

问题描述 投票:0回答:1

`我们如何使用 SMOTE 来解决 Tensorflow 中对象检测的类不平衡问题,其中模型输出是标签和 bbox?

这是我的代码,但我无法弄清楚应该在哪里以及如何使用 smote 来解决类不平衡问题?`

import imutils
import os
import cv2
import datetime
import numpy as np



import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.models import load_model
from tensorflow.keras.applications import VGG16, resnet50, inception_v3
from tensorflow.keras.layers import Dropout
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelBinarizer

import pickle

import pandas as pd
train_df = pd.read_csv('train.csv')
train_df.head()

print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

# renaming the columns 
train_df = train_df.rename(columns={'img_fName': 'ImageID','img_w':'width','img_h':'height','bbx_xtl':'Xmin', 'bbx_ytl':'Ymin', 'bbx_xbr':'Xmax',
       'bbx_ybr':'Ymax', 'class_label':'ClassName'})
train_df.head()

for idx, row in enumerate(train_df):
    print(row)

data = []
labels1 = []
bboxes = []
imagePaths = []
for index, row in train_df.iterrows():
    (filename, width, height, xmin, ymin, xmax, ymax,class_name) = row
    #labels.append(class_name)
    Xmin = float(xmin)/width
    Ymin = float(ymin)/height
    Xmax = float(xmax)/width
    Ymax = float(ymax)/height
    filename = "train_images/"+filename
    image = cv2.imread(filename)
    (h,w) = image.shape[:2]
    image = load_img(filename, target_size=(224,224))
    image = img_to_array(image)
    data.append(image)
    labels1.append(class_name)
    bboxes.append((Xmin, Ymin, Xmax, Ymax))
    imagePaths.append(filename)
    print(len(imagePaths))

# show the output image
img = plt.imshow(image.astype('uint8'))
#cv2.rectangle(image,(Xmin,Ymin),(Xmax,Ymax),(255,0,0),2)
plt.show()


# convert from the range [0, 255] to [0, 1]
data = np.array(data, dtype="float32") / 255.0

# convert to numpy array
labels = np.array(labels1)
bboxes = np.array(bboxes, dtype="float32")
imagePaths = np.array(imagePaths)

# one-hot encoding on the labels
lb = LabelBinarizer()
labels = lb.fit_transform(labels)



if len(lb.classes_) == 2:
    print("two classes")
    labels = to_categorical(labels)



split = train_test_split(data,
                         labels,
                         bboxes,
                         imagePaths,
                         test_size=0.20,
                         random_state=42)


labels.shape



# unpack the data split
(trainImages, testImages) = split[:2]
(trainLabels, testLabels) = split[2:4]
(trainBBoxes, testBBoxes) = split[4:6]
(trainPaths, testPaths) = split[6:]

#vgg = VGG16(weights="imagenet",
#            include_top=False,
#            input_tensor=Input(shape=(224, 224, 3)))
InceptionV3 = tf.keras.applications.inception_v3.InceptionV3(
    include_top=False,
    weights='imagenet',
   input_tensor=Input(shape=(224, 224, 3))    #input_shape=None,
   # pooling=None,
)




# freeze all layers in order not to train them
InceptionV3.trainable = False





# flatten the max-pooling output of 
flatten = InceptionV3.output
flatten = Flatten()(flatten)



# construct a fully-connected layer 
# header to output the predicted
# bounding box coordinates

bboxHead = Dense(128, activation="relu")(flatten)
bboxHead = Dense(64, activation="relu")(bboxHead)
bboxHead = Dense(32, activation="relu")(bboxHead)
bboxHead = Dense(4, activation="sigmoid", name="bounding_box")(bboxHead)

# construct a second fully-connected 
# layer header to predict
# the class label

softmaxHead = Dense(512, activation="relu")(flatten)
softmaxHead = Dropout(0.5)(softmaxHead)
softmaxHead = Dense(512, activation="relu")(softmaxHead)
softmaxHead = Dropout(0.5)(softmaxHead)
softmaxHead = Dense(len(lb.classes_), activation="softmax", name="class_label")(softmaxHead)

species_class_weights = {
    0: 3567/38, #aegypti
    1:1.0, # albopictus
    2: 3544/63,
    3: 3544/3544,
    4: 3544/492,
    5: 3544/321
}

model = Model(
    inputs=InceptionV3.input,
    outputs=(bboxHead, softmaxHead))

INIT_LR = 1e-4
NUM_EPOCHS = 20
BATCH_SIZE = 15



losses = {
    "class_label": "categorical_crossentropy",
    "bounding_box": "mean_squared_error",
}



lossWeights = {
    "class_label": species_class_weights,
    "bounding_box": 1.0
}



#We need to construct a dictionary for our target training outputs.

trainTargets = {
    "class_label": trainLabels,
    "bounding_box": trainBBoxes
}



#We need to construct a second dictionary, this one for our target testing outputs.

testTargets = {
    "class_label": testLabels,
    "bounding_box": testBBoxes
}



opt = Adam(INIT_LR)

model.compile(loss=losses, 
              optimizer=opt, 
              metrics=["accuracy"], 
              loss_weights=lossWeights)

print(model.summary())


` Train Neural Network Here we train our network for bounding box regression and class label prediction.`

H = model.fit(
    trainImages, trainTargets,
    validation_data=(testImages, testTargets),
    batch_size=BATCH_SIZE,
    epochs=NUM_EPOCHS,
    verbose=1)

我无法找到在哪里以及如何添加 smote 来处理类别不平衡

tensorflow deep-learning conv-neural-network data-science smote
1个回答
0
投票

要使用

SMOTE
,我们可以在脚本的开头添加以下内容:

import pandas as pd

from imblearn.over_sampling import SMOTE


train_df = pd.read_csv('train.csv')

# renaming the columns 
train_df = train_df.rename(columns={'img_fName': 'ImageID', 
                                    'img_w': 'width', 
                                    'img_h': 'height', 
                                    'bbx_xtl':'Xmin', 
                                    'bbx_ytl':'Ymin',
                                    'bbx_xbr':'Xmax',
                                    'bbx_ybr':'Ymax', 
                                    'class_label':'ClassName'})

# transform the dataset
X = train_df[['ImageID', 'width', 'height', 'Xmin', 'Ymin', 'Xmax', 'Ymax']]
y = train_df['ClassName']
oversample = SMOTE()
X_res, y_res = oversample.fit_resample(X, y)
``
© www.soinside.com 2019 - 2024. All rights reserved.