Перейти к содержимому
Compvision.ru
prim.ko

Multi-class segmentation with a UNet

Recommended Posts

Приветствую. 

Начал разбираться с сеткой UNet. Нашел реализацию на Keras + Theano, которой на кагле сегментировали нервы. В конкурсе изображения имели бинарные маски. А как подготавливать и скармливать сетке маски, если имеем несколько классов? Есть примеры кода? 

И как создавать такие маски? Это будут просто заранее заданные цвета, или лучше перевести в градации серого с одним каналом?

 

Вот пример реализации UNet, где мужик подготавливает данные в *npy

from __future__ import print_function

import os
from skimage.transform import resize
from skimage.io import imsave
import numpy as np
from keras.models import Model
from keras.layers import Input, concatenate, Conv2D, MaxPooling2D, UpSampling2D
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint
from keras import backend as K

from data import load_train_data, load_test_data

#prepare train data
def create_train_data():
    train_data_path = os.path.join(data_path, 'train')
    images = os.listdir(train_data_path)
    total = len(images) / 2         # учитываем маски и тренировочные

    imgs = np.ndarray((total, image_rows, image_cols), dtype=np.uint8)
    imgs_mask = np.ndarray((total, image_rows, image_cols), dtype=np.uint8)

    i = 0
    print('-'*30)
    print('Creating training images...')
    print('-'*30)
    for image_name in images:
        if 'mask' in image_name:
            continue
        image_mask_name = image_name.split('.')[0] + '_mask.tif'
        img = imread(os.path.join(train_data_path, image_name), as_grey=True)
        img_mask = imread(os.path.join(train_data_path, image_mask_name), as_grey=True)

        img = np.array([img])
        img_mask = np.array([img_mask])

        imgs[i] = img
        imgs_mask[i] = img_mask

        if i % 100 == 0:
            print('Done: {0}/{1} images'.format(i, total))
        i += 1
    print('Loading done.')

    np.save('imgs_train.npy', imgs)
    np.save('imgs_mask_train.npy', imgs_mask)
    print('Saving to .npy files done.')
    
    from __future__ import print_function


img_rows = 96
img_cols = 96

smooth = 1.


def dice_coef(y_true, y_pred):
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)


def dice_coef_loss(y_true, y_pred):
    return -dice_coef(y_true, y_pred)


def get_unet():
    inputs = Input((img_rows, img_cols, 1))
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)

    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)

    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)

    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)

    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)

    up6 = concatenate([UpSampling2D(size=(2, 2))(conv5), conv4], axis=3)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)

    up7 = concatenate([UpSampling2D(size=(2, 2))(conv6), conv3], axis=3)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)

    up8 = concatenate([UpSampling2D(size=(2, 2))(conv7), conv2], axis=3)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)

    up9 = concatenate([UpSampling2D(size=(2, 2))(conv8), conv1], axis=3)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)

    conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)

    model = Model(inputs=[inputs], outputs=[conv10])

    model.compile(optimizer=Adam(lr=1e-5), loss=dice_coef_loss, metrics=[dice_coef])

    return model


def preprocess(imgs):
    imgs_p = np.ndarray((imgs.shape[0], img_rows, img_cols), dtype=np.uint8)
    for i in range(imgs.shape[0]):
        imgs_p[i] = resize(imgs[i], (img_cols, img_rows), preserve_range=True)

    imgs_p = imgs_p[..., np.newaxis]
    return imgs_p


def train_and_predict():
    print('-'*30)
    print('Loading and preprocessing train data...')
    print('-'*30)
    imgs_train, imgs_mask_train = load_train_data()

    imgs_train = preprocess(imgs_train)
    imgs_mask_train = preprocess(imgs_mask_train)

    imgs_train = imgs_train.astype('float32')
    mean = np.mean(imgs_train)  # mean for data centering
    std = np.std(imgs_train)  # std for data normalization

    imgs_train -= mean
    imgs_train /= std

    imgs_mask_train = imgs_mask_train.astype('float32')
    imgs_mask_train /= 255.  # scale masks to [0, 1]

    print('-'*30)
    print('Creating and compiling model...')
    print('-'*30)
    model = get_unet()
    model_checkpoint = ModelCheckpoint('weights.h5', monitor='val_loss', save_best_only=True)

    print('-'*30)
    print('Fitting model...')
    print('-'*30)
    model.fit(imgs_train, imgs_mask_train, batch_size=32, nb_epoch=20, verbose=1, shuffle=True,
              validation_split=0.2,
              callbacks=[model_checkpoint])

    print('-'*30)
    print('Loading and preprocessing test data...')
    print('-'*30)
    imgs_test, imgs_id_test = load_test_data()
    imgs_test = preprocess(imgs_test)

    imgs_test = imgs_test.astype('float32')
    imgs_test -= mean
    imgs_test /= std

    print('-'*30)
    print('Loading saved weights...')
    print('-'*30)
    model.load_weights('weights.h5')

    print('-'*30)
    print('Predicting masks on test data...')
    print('-'*30)
    imgs_mask_test = model.predict(imgs_test, verbose=1)
    np.save('imgs_mask_test.npy', imgs_mask_test)

    print('-' * 30)
    print('Saving predicted masks to files...')
    print('-' * 30)
    pred_dir = 'preds'
    if not os.path.exists(pred_dir):
        os.mkdir(pred_dir)
    for image, image_id in zip(imgs_mask_test, imgs_id_test):
        image = (image[:, :, 0] * 255.).astype(np.uint8)
        imsave(os.path.join(pred_dir, str(image_id) + '_pred.png'), image)

if __name__ == '__main__':
    train_and_predict()

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Возможно можно посчитать dice loss для каждого выхода - sigmoid'ы  и проссумировать, чтобы получить общий loss, но не уверен.

А так в терминах keras'а можно использовать sigmoid + binary_crossentropy или softmax + categorical_crossentropy.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Так есть же SEGNET на том же Keras, можно там посмотреть: https://github.com/imlab-uiip/keras-segnet

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я смотрел эту репу и там как раз непонятно как всё делается так что не рекомендую.

Ибо загрузка из json, по мне так менее читаемо чем модель на питоне. А так там походу стандартный трюк с reshape+permute используется.

https://github.com/imlab-uiip/keras-segnet/blob/master/model_5l.json

Да и репа мертвая походу, на вопросы не отвечают

https://github.com/imlab-uiip/keras-segnet/issues/12

 

Как я понял в ф-ию которая считает crossentropy можно подавать матрицу и сумма по последнему дименшену должна быть 1.0 (т.е. после softmax), т.е. он посчитает по каждому row и проссумирует loss. Но всё это делается в неявном виде так что не очень приятно.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ученые мужики, подскажите что почитать по проектированию сетей на Caffe. Дело в том, что пытаюсь переписать U-Net на Caffe. И описание моделей в prototxt это совсем не ванильный Keras. Многое, что в Keras остается "черным ящиком" теперь не дает мне построить сетку на Caffe. Например начал с первой группы слоев U-Net

599d1b5ee981a__018.png.9eaa17fc9640d7c603eb7a53c1988804.png 

(Картинка взята из dstl)

layer {
  name: "label"
  type: "Data"
  top: "label"

  include {
    phase: TRAIN
  }
    transform_param {
    mirror: true
  }
  data_param {
    batch_size: 5
    backend: LMDB
  }
}
layer {
  name: "data"
  type: "Data"
  top: "data"

  include {
    phase: TEST
  }
    transform_param {
    mirror: true
  }
  data_param {
    batch_size: 5
    backend: LMDB
  }
}
layer {
  name: "label"
  type: "Data"
  top: "label"

  include {
    phase: TEST
  }
    transform_param {
    mirror: true
  }
  data_param {
    batch_size: 5
    backend: LMDB
  }
}
# data layers
layer {
  name: "data"
  type: "Data"
  top: "data"

  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
  }
  data_param {
    batch_size: 5
    backend: LMDB
  }
}
#-------------layer group 1---------------
layer {
  name: "conv1a"
  type: "Convolution"
  bottom: "data"
  top: "conv1a"

  convolution_param {
    num_output: 32 
    kernel_size: 3
    pad: 1
    stride: 1
    engine: CUDNN
    weight_filler {
      type: "xavier"
      #std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {
  name: "conv1a_BN"
  type: "BatchNorm"
  bottom: "conv1a"
  top: "conv1a_BN"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: false
    moving_average_fraction: 0.95
  }
}

layer {
  name: "elu1"
  type: "ELU" elu_param { alpha: 1.0}
  bottom: "conv1a_BN"
  top: "conv1a_BN"
}

layer {
  name: "conv1b"
  type: "Convolution"
  bottom: "conv1a_BN"
  top: "conv1b"

  convolution_param {
    num_output: 32 
    kernel_size: 3
    pad: 1
    stride: 1
    engine: CUDNN
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {
  name: "conv1b_BN"
  type: "BatchNorm"
  bottom: "conv1b"
  top: "conv1b_BN"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: false
    moving_average_fraction: 0.95
  }
}

layer {
  name: "elu2"
  type: "ELU" elu_param { alpha: 1.0}
  bottom: "conv1b_BN"
  top: "conv1b_BN"
}



layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "conv1b_BN"
  bottom: "label"
  top: "loss"
  include: { phase: TRAIN }
}

После загрузки данной сетки в DIGITS - тишина. В качестве обучения использую разметку дорог toronto dataset https://www.cs.toronto.edu/~vmnih/data/ .  Там бинарная разметка. 

В DIGITS подготовил датасет для сегментации. Интерполировал его к разрешению 500*500 и указал "color map specification" from text file. В нем  указал

255 255 255
0 0 0

В общем не понятно, почему не шевелится DIGITS?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Тишина всмысле не обучается? В DIGITS там какой то баг был с BatchNorm, всмысле nvidia-caffe ветка, так что лучше использовать caffe-master.

Еще загрузку данных бы неплохо проверить, вы от какого примера отталкивались?

А где у вас Upsampling layer или вы сейчас с уменьшенными масками учите?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, mrgloom сказал:

Тишина всмысле не обучается? В DIGITS там какой то баг был с BatchNorm, всмысле nvidia-caffe ветка, так что лучше использовать caffe-master.

Еще загрузку данных бы неплохо проверить, вы от какого примера отталкивались?

А где у вас Upsampling layer или вы сейчас с уменьшенными масками учите?

Да, не обучается. 

Строю сетку и смотрю, на что caffe ругается. Пока не добавил Deconvolution layer. 

Добавил в модель слой deconv и accuracy  и все заработало. Только конечно при тестировании обученной модели показывает темное изображение. выход не правильный?

layer {
  name: "conv1a"
  type: "Convolution"
  bottom: "data"
  top: "conv1a"

  convolution_param {
    num_output: 32 
    kernel_size: 3
    pad: 1
    stride: 1
    engine: CUDNN
    weight_filler {
      type: "xavier"
      #std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {
  name: "conv1a_BN"
  type: "BatchNorm"
  bottom: "conv1a"
  top: "conv1a_BN"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: false
    moving_average_fraction: 0.95
  }
}

layer {
  name: "elu1"
  type: "ELU" elu_param { alpha: 1.0}
  bottom: "conv1a_BN"
  top: "conv1a_BN"
}

layer {
  name: "conv1b"
  type: "Convolution"
  bottom: "conv1a_BN"
  top: "conv1b"

  convolution_param {
    num_output: 32 
    kernel_size: 3
    pad: 1
    stride: 1
    engine: CUDNN
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

layer {
  name: "conv1b_BN"
  type: "BatchNorm"
  bottom: "conv1b"
  top: "conv1b_BN"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: false
    moving_average_fraction: 0.95
  }
}
layer {
  name: "elu2"
  type: "ELU" elu_param { alpha: 1.0}
  bottom: "conv1b_BN"
  top: "conv1b_BN"
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1b_BN"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "up_deconv1"
  type: "Deconvolution"
  bottom: "pool1"
  top: "up_deconv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  convolution_param {
    num_output: 32
    kernel_size: 2
    stride: 2
  }
}

layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "up_deconv1"
  bottom: "label"
  top: "loss"
  include: { phase: TRAIN }
}

layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "up_deconv1"
  bottom: "label"
  top: "accuracy"
  include { stage: "val" }
}

599d5009c51ba__027.thumb.png.eb102cd9a45028e7ec7a15bbd2fa56b8.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Может просто значения маленькие, попробуйте привести в диапазон, который будет видно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
num_output: 32

У вас 32 класса?

 

А так в DIGITS же можно смотреть активации для всех блобов, по крайней мере для классификации.

 

И вы загрузку данных как в каком примере используете?

https://github.com/NVIDIA/DIGITS/tree/master/examples/binary-segmentation

https://github.com/NVIDIA/DIGITS/tree/master/examples/medical-imaging

https://github.com/NVIDIA/DIGITS/tree/master/examples/semantic-segmentation

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, mrgloom сказал:

num_output: 32

У вас 32 класса?

 

А так в DIGITS же можно смотреть активации для всех блобов, по крайней мере для классификации.

 

И вы загрузку данных как в каком примере используете?

https://github.com/NVIDIA/DIGITS/tree/master/examples/binary-segmentation

https://github.com/NVIDIA/DIGITS/tree/master/examples/medical-imaging

https://github.com/NVIDIA/DIGITS/tree/master/examples/semantic-segmentation

Использовал что-то похожее на https://github.com/NVIDIA/DIGITS/tree/master/examples/semantic-segmentation

Сконструировал всю сетку unet_train_new.prototxt . DIGITS ругается:

599d7382381f3__028.thumb.png.5298993f87ccb1ae8979e7b730cf6747.png

Подаю ему вот такие данные:

599d73b0aad6e__029.png.5af635ab0436c9b3b95efbfeac6e780e.png

Не до конца понял, чего ему не нравится?

Без названия.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вроде как заработало, если исправить у последнего сверточного слоя "G10_a1_conv" параметр pad=0. В итоге вышла вот такая U-Net unet_train_new.prototxt . Вот только обучаться это чудо не хочет.  Показывает при тестировании белые изображения.

599d8b7a33eda__030.png.663c7bb1c8d8694a1f585e4a7621b8d8.png

Причем при просмотре статистики Infer One Image.html только первый сверточный слой активируется нормально, а затем вообще ничего. Может это связано с вычитанием среднего?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Нормализовать инпут надо обязательно как zero mean unit vairance, говорят что можно batchnorm запихнуть сразу после инпута.

 

По картинкам видно что активации нет на следующих слоях, попробуйте learning rate уменьшить или batch size увеличить, еще в caffe + DIGITS можно делать batch accumulation если по памяти не влезает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А родители скорости обучения равные нулям , это так и задумано?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 час назад, mrgloom сказал:

Нормализовать инпут надо обязательно как zero mean unit vairance, говорят что можно batchnorm запихнуть сразу после инпута.

 

По картинкам видно что активации нет на следующих слоях, попробуйте learning rate уменьшить или batch size увеличить, еще в caffe + DIGITS можно делать batch accumulation если по памяти не влезает.

Как это делается примерно? learning rate стоит изначально на 0.01 затем уменьшается с exponential Decay

599e4eba9fda5__031.png.d5d92812aabf5bebd7066781d54f83e3.png

А про batch accumulation ребята вот что пишут на примере detectnet. На 1080 влазит размер батча 12 (картинки 256*256). По совету ребят вроде как нужно не больше единицы установить 

599e55e7a9e29__032.thumb.png.c8df880b997ceec20822f69e89dd68d6.png

 

10 часов назад, Smorodov сказал:

А родители скорости обучения равные нулям , это так и задумано?

param {
    lr_mult: 0
    decay_mult: 0
  }

Эти параметры не знал вообще что делают. Для чего их предназначение?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

lr_mult: 0  типо фризит лайер т.е. сеть не учится.

Вроде как можно вообще это убрать, т.е. будет по дефолту.

Например

https://github.com/mrgloom/kaggle-dogs-vs-cats-solution/blob/master/finetuning/VGG16/original.prototxt

 

Картинка про batch accumulation значит что (в зависимости от памяти доступной на GPU) можно получить effective batch size=10 как 2*5 или 5*2 или 10*1.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
40 минут назад, mrgloom сказал:

lr_mult: 0  типо фризит лайер т.е. сеть не учится.

Ясно. Значит можно просто установить размер батча равным 12 и не указывать "accumulation".

Вообщем моя ошибка - поучил сеть 10 эпох и бежал смотреть вывод. По этому ничего и не показывала. Убрал все BN и поучил 70 эпох (600 картинок) вывод получил. Значит сеть учится. Но только почему с BN не учится? Установил даже lr_mult=1, decay_mult=1

 599ea35e22f0d__033.png.de7da7228b2c9b9b76660179a208a288.png

Есть вопрос у меня еще по поводу функции активации. в оригинальном U-NET использовали dice loss либо jackard. Как возможно сюда это запилить?

Получается глупая картинка при обучении:

599ea4207c5d1__034.png.800478eebdfb5e5b358b883e0335d887.png

 

После первой эпохи accuracy достигает 0.94 и так и держится чуть-чуть (+- 0.001) изменяясь.

Тут явно какой-то криминал. Последние слои сделал вот так:

 

599ea4eb1305a__035.png.30b3884eeb27cc67cf0eeceeac01473e.png

 

layer {
  name: "G10_a1_conv"
  type: "Convolution"
  bottom: "G9_d1_conv"
  top: "G10_a1_conv"

  convolution_param {
    num_output: 2
    kernel_size: 1
    pad: 0
    engine: CUDNN
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "G10_a1_conv"
  bottom: "label"
  top: "loss"
  loss_param {
    normalize: true
  }
  exclude {
    stage: "deploy"
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "G10_a1_conv"
  bottom: "label"
  top: "accuracy"
  include { stage: "val" }
}

Есть предположения в чем может быть дело?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно попробовать learning rate поменьше имея уже предобученную модель.

 

dice loss можно сделать через custom python layer

https://github.com/NVIDIA/DIGITS/tree/master/examples/python-layer

 

Я кстати не знаю как выбор loss'а будет влиять на форму\качество предсказанной маски это вопрос интересный.

Еще в dice loss есть некий smooth parameter, по идее это же может быть просто что типа eps=1e-3, чтобы не было деления на 0 или это как то влияет на предсказание границ?

Тут 1.0

https://github.com/jocicmarko/ultrasound-nerve-segmentation/blob/master/train.py#L23

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 минуты назад, mrgloom сказал:

Еще в dice loss есть некий smooth parameter, по идее это же может быть просто что типа eps=1e-3, чтобы не было деления на 0 или это как то влияет на предсказание границ?

При изменении данного параметра я никаких сдвигов не увидел. Я использовал 1е-6. 

 

12 минуты назад, mrgloom сказал:

Можно попробовать learning rate поменьше имея уже предобученную модель.

У меня нет предобученной модели. Или речь идет например о VGG-16? Это возможно сюда прикрутить чтобы не обучаться с ноля? И поможет ли это в данном случае, ведь картинки спутниковые, а ImageNet содержит совсем другие классы. Опять таки почему с BN не работает?) Мало 70 эпох?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Имеется ввиду ту модель которую вы уже обучили и которая что то уже выводит.

 

Я говорю с BN там был баг.

Выложу в эту репу потом модель resnet'ов которые работают, там как раз были проблемы с BN насколько я помню.

https://github.com/mrgloom/kaggle-dogs-vs-cats-solution

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Та модель, которую обучил - без bn. В keras я пробовал изменять модель после того как обучил. Добавлял слои и загружал веса от старой - так нельзя. В Caffè  ведь так же

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно загружать веса и там и там, а вот добавлять потом слои уже сложнее и скорее всего это делается тупо копированием весов из одной модели (из менее короткой в более длинную) в другую.

Но изначально я предлагал именно доучить ту же самую модель (с загруженными весами от предыдущего запуска, которые уже что то дают похожее на правду) с меньшим learning rate.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В общем через боль, страдания, подбор параметров и еще танцев с бубном проблема решена. Надеюсь кому-то поможет эта информация.

Почему-то по умолчанию в DIGITS ( использовал docker nvidia-digits-rc-6.0)  в слое типа BatchNorm ( а может быть и в других слоях ) используется CUDNN engine в противовес CAFFE engine, если этого не задавать явно. Мужики пишут по этому поводу вот что:

Цитата

Top and bottom blobs need to be different for engine:CUDNN BatchNorm. This constraint is not there for engine:CAFFE BatchNorm. This is the reason for non-convergence.

Теперь Caffe BN слой для использования его в DIGITS выглядит вот так:

layer {
  name: "G9_d2_bn"
  type: "BatchNorm"
  bottom: "G9_d1_conv"
  top: "G9_d2_bn"
  param { #scale
    lr_mult: 1
    decay_mult: 1
  }
  param { #shift/bias
    lr_mult: 1
    decay_mult: 1
  } 
  param { #global mean
    lr_mult: 0
    decay_mult: 0
  }
  param { #global var
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    scale_filler {
    type: "constant"
    value: 1
    }
    bias_filler {
      type: "constant"
      value: 0
    }
    engine: CUDNN
    use_global_stats: false
  }
}

Интересно, что при использовании CUDNN engine память gpu отжирается вот так:

59a0080b7eb5f__001.png.c6e0f6e5ab417c90c29f251e3988ac52.png

Если установить CAFFE engine:

59a009199167a__002.png.765bb9ffa4b40e3e863bca29df85f3fa.png

 

За одинаковое время обучения сеть с использованием CUDNN engine заврешила 15 эпох. С использованием CAFFE engine 7 эпох.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Честно говоря, думал что если caffe собран с включенной cudnn, то он ее будет по умолчанию использовать.

А так да, cudnn сильно ускоряет процесс и экономит память. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Раньше в .prototxt нельзя было указывать 'engine' это что то новое, а просто caffe собирается с CUDNN, т.е. это указывается в makefile.

Видимо теперь можно собрать с CUDNN, но свитчить engine не перекомпилируя?

По дефолту вроде сейфово стоит то что надо

https://stackoverflow.com/a/43306411/1179925

 

По идее и без BN должно работать, на график сходимости интересно посмотреть с и без.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 часа назад, mrgloom сказал:

По идее и без BN должно работать, на график сходимости интересно посмотреть с и без.

 У меня выборка большая. Настроить BN было принципиально. 

Не знаю как обстоят дела с caffe, которую собирать ручками,  в dockere так.

Dice loss прикрутил. Довольно удобно оказалось, что можно юзать python layer. С ним другое дело. Стандартный softmaxwithloss грустно относится к неравномерно распределеным классам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×