Как я могу повысить точность своей сети классификации изображений?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как я могу повысить точность своей сети классификации изображений?

Сообщение Anonymous »

Я имею дело с довольно специфичной задачей классификации изображений. По сути, я обрезал изображения сперматозоидов следующим образом:
Пример обрезанного изображения
Точный размер кадра в пикселях определяется текущим архитектуру модели, но я работаю примерно с входами 200х200. Эти входные данные представляют собой нормализованные черно-белые изображения, к которым применяется увеличение данных в виде изменения яркости и контрастности, а также поворотов и переворотов (по горизонтали и вертикали). Я проверил и уверен, что полностью предварительно обработанные изображения содержат необходимую информацию, поэтому входные данные модели отформатированы правильно. У меня есть около 6000 изображений, разделенных на обучающие, проверочные и тестовые наборы (65-25-10%), в среднем от 6 до 10 сперматозоидов на фото.
Я также успешно это сделал. обучили и протестировали аналогичную модель, примененную к сперме, но объекты на фотографиях были намного меньше, примерно в 3-4 раза меньше. Я пытался адаптировать сетевые архитектуры, которые я разработал для решения этой проблемы, но они неэффективны.
У меня есть 4 разных класса, которые определяют состояние головки сперматозоида: нормальная, поврежденная, повернут и не в фокусе:
Нормальный[Повреждён](https://i.sstatic.net/f5z5VAI6.png[Нефокусирован](https://i.sstatic.net/MVRjDGpB. png)[Turned](https://i.sstatic.net/tR94Hayf.png)
У меня также есть 5-й класс, который каталогизирует каждый элемент, обнаруженный на фотографии, который не является спермой ( например, грязь или бактерии). Это результат предыдущей модели обнаружения, которую я обучил на этом наборе данных, и она работает очень хорошо, поэтому по сути это оставшиеся ложные срабатывания, которые я хочу отфильтровать:
FP
С учетом вышесказанного логика модели в моем коде следующая:

Код: Выделить всё

class MobileNetV3Inspired(BaseClassifier):

def _make_block(self, inputs, filters, expansion, strides, ix, dilation_rate=1):
# Define the number of input channels
input_channels = inputs.shape[-1]

# Apply a 1x1 convolution to the inputs to perform channel-wise compression
x = tf.keras.layers.Conv2D(expansion * input_channels, kernel_size=1,
name=f"1x1conv_{ix}")(inputs)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Lambda(hard_swish)(x)

# Apply a depthwise separable convolution to capture both local and global information
x = tf.keras.layers.DepthwiseConv2D(kernel_size=3,
strides=strides,
dilation_rate=dilation_rate,  # Include dilation
padding="same",
name=f"dwconv_{ix}")(x)

x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Lambda(hard_swish)(x)

x = tf.keras.layers.Conv2D(filters, kernel_size=1)(x)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Lambda(hard_swish, name=f"hard_swish_{ix}")(x)

return x

def _make_inner_layers(self, x):
for ix, block in enumerate(self._blocks):
dilation_rate = block.get("dilation_rate", 1)
x = self._make_block(x,
block["filters"],
block["expansion"],
block["stride"],
ix=ix,
dilation_rate=dilation_rate)
return x

def _grow_patch_size_inner(self, size):
for block in reversed(self._blocks):
size = (size - 1) * block["stride"] + 3
return size
Текущие значения гиперпараметров определены в файле конфигурации, и эта конфигурация на данный момент является лучшей (точность около 77 % при проверке и около 40 % при тестировании):
р>

Код: Выделить всё

mnv3_inspired_deep_v2:
body_driver: mobilenetv3

blocks:
- {filters: 32, expansion: 3, stride: 3}
- {filters: 64, expansion: 3, stride: 3, dilation_rate: 2}
- {filters: 96, expansion: 3, stride: 1}  # Intermediate layer, maintain size
- {filters: 128, expansion: 4, stride: 2, dilation_rate: 2}
- {filters: 128, expansion: 4, stride: 1} # Maintain size
- {filters: 192, expansion: 4, stride: 2, dilation_rate: 2}
- {filters: 192, expansion: 4, stride: 1} # Maintain size
- {filters: 256, expansion: 4, stride: 2}
- {filters: 256, expansion: 4, stride: 1, dilation_rate: 2} # Maintain size

dense:
- {filters: 256, dropout_rate: 0.4}
- {filters: 128, dropout_rate: 0.3}
- {filters: 64, dropout_rate: 0.2}
Для справки: в моей последней задаче с меньшими объектами очень хорошо сработала следующая сеть, учитывая, что входные изображения также были примерно вдвое меньше:

Код: Выделить всё

mnv3_inspired:
body_driver: mobilenetv3

blocks:
- {filters: 30, expansion: 5, stride: 3}
- {filters: 60, expansion: 5, stride: 3}
- {filters: 60, expansion: 5, stride: 2}
- {filters: 60, expansion: 5, stride: 2}
- {filters: 100, expansion: 5, stride: 1}
- {filters: 100, expansion: 5, stride: 1}

dense:
- {filters: 60, dropout_rate: 0.3}
Таким образом, у меня есть входной слой, серия блоков свертки, которые следуют этой структуре (количество и значения гиперпараметров которых определены в файле конфигурации), и выходной слой softmax. с 5 классами.
Я использую tf.keras.metrics.categorical_crossentropy(gt, pred, from_logits=False) в качестве функции потерь, но я также пробовал другие, например функцию потерь, которая присваивает классам веса в зависимости от количества примеров:

Код: Выделить всё

def compute_class_weights(y_true):
"""Compute class weights based on the distribution of the ground truth labels.

Args:
y_true (ndarray): One-hot encoded ground truth labels.

Returns:
class_weights (ndarray): Array of weights for each class.
"""
class_totals = np.sum(y_true, axis=0)
total_samples = np.sum(class_totals)

# To avoid division by zero, set the weights for classes with zero samples to a small constant
epsilon = 1e-6  # Small constant
class_totals = np.where(class_totals == 0, epsilon, class_totals)

# Calculate weights as inverse of class frequencies
class_weights = total_samples / (len(class_totals) * class_totals)

class_weights[0] *= 1

return class_weights
Что касается весов классов, у меня нет серьезной проблемы с дисбалансом классов, но «нормальный» класс является наиболее распространенным, а «поврежденные» и «несфокусированные» классы являются наиболее распространенными. важно правильно классифицировать.
Я также уменьшаю скорость обучения (начальная 0,001), когда потери не улучшаются, и использую раннюю остановку:

Код: Выделить всё

history = model.fit(train_dl,
epochs=EPOCHS,
validation_data=val_dl,
callbacks=[
EarlyStopping(monitor='val_loss', patience=LR_FLAT_EPOCHS*3),
ReduceLROnPlateau(monitor='val_loss', factor=0.01, patience=LR_FLAT_EPOCHS*2, min_lr=0.00001, mode='auto', verbose=1),
TerminateOnNaN(),
checkpoint_callback
])
Какие элементы изменить в моем коде/дизайне, чтобы еще больше повысить точность модели?

Подробнее здесь: https://stackoverflow.com/questions/791 ... on-network
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»