prim.ko 3 Report post Posted April 25, 2017 Приветствую. Начал разбираться с сеткой 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() Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 11, 2017 Возможно можно посчитать dice loss для каждого выхода - sigmoid'ы и проссумировать, чтобы получить общий loss, но не уверен. А так в терминах keras'а можно использовать sigmoid + binary_crossentropy или softmax + categorical_crossentropy. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 11, 2017 Так есть же SEGNET на том же Keras, можно там посмотреть: https://github.com/imlab-uiip/keras-segnet Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 11, 2017 Я смотрел эту репу и там как раз непонятно как всё делается так что не рекомендую. Ибо загрузка из 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. Но всё это делается в неявном виде так что не очень приятно. Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 23, 2017 Ученые мужики, подскажите что почитать по проектированию сетей на Caffe. Дело в том, что пытаюсь переписать U-Net на Caffe. И описание моделей в prototxt это совсем не ванильный Keras. Многое, что в Keras остается "черным ящиком" теперь не дает мне построить сетку на Caffe. Например начал с первой группы слоев U-Net (Картинка взята из 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? Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 23, 2017 Тишина всмысле не обучается? В DIGITS там какой то баг был с BatchNorm, всмысле nvidia-caffe ветка, так что лучше использовать caffe-master. Еще загрузку данных бы неплохо проверить, вы от какого примера отталкивались? А где у вас Upsampling layer или вы сейчас с уменьшенными масками учите? Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 23, 2017 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" } } Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 23, 2017 Может просто значения маленькие, попробуйте привести в диапазон, который будет видно. Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 23, 2017 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 Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 23, 2017 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 ругается: Подаю ему вот такие данные: Не до конца понял, чего ему не нравится? Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 23, 2017 Вроде как заработало, если исправить у последнего сверточного слоя "G10_a1_conv" параметр pad=0. В итоге вышла вот такая U-Net unet_train_new.prototxt . Вот только обучаться это чудо не хочет. Показывает при тестировании белые изображения. Причем при просмотре статистики Infer One Image.html только первый сверточный слой активируется нормально, а затем вообще ничего. Может это связано с вычитанием среднего? Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 23, 2017 Нормализовать инпут надо обязательно как zero mean unit vairance, говорят что можно batchnorm запихнуть сразу после инпута. По картинкам видно что активации нет на следующих слоях, попробуйте learning rate уменьшить или batch size увеличить, еще в caffe + DIGITS можно делать batch accumulation если по памяти не влезает. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 23, 2017 А родители скорости обучения равные нулям , это так и задумано? Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 24, 2017 11 час назад, mrgloom сказал: Нормализовать инпут надо обязательно как zero mean unit vairance, говорят что можно batchnorm запихнуть сразу после инпута. По картинкам видно что активации нет на следующих слоях, попробуйте learning rate уменьшить или batch size увеличить, еще в caffe + DIGITS можно делать batch accumulation если по памяти не влезает. Как это делается примерно? learning rate стоит изначально на 0.01 затем уменьшается с exponential Decay А про batch accumulation ребята вот что пишут на примере detectnet. На 1080 влазит размер батча 12 (картинки 256*256). По совету ребят вроде как нужно не больше единицы установить 10 часов назад, Smorodov сказал: А родители скорости обучения равные нулям , это так и задумано? param { lr_mult: 0 decay_mult: 0 } Эти параметры не знал вообще что делают. Для чего их предназначение? Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 24, 2017 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. 1 Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 24, 2017 40 минут назад, mrgloom сказал: lr_mult: 0 типо фризит лайер т.е. сеть не учится. Ясно. Значит можно просто установить размер батча равным 12 и не указывать "accumulation". Вообщем моя ошибка - поучил сеть 10 эпох и бежал смотреть вывод. По этому ничего и не показывала. Убрал все BN и поучил 70 эпох (600 картинок) вывод получил. Значит сеть учится. Но только почему с BN не учится? Установил даже lr_mult=1, decay_mult=1 Есть вопрос у меня еще по поводу функции активации. в оригинальном U-NET использовали dice loss либо jackard. Как возможно сюда это запилить? Получается глупая картинка при обучении: После первой эпохи accuracy достигает 0.94 и так и держится чуть-чуть (+- 0.001) изменяясь. Тут явно какой-то криминал. Последние слои сделал вот так: 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" } } Есть предположения в чем может быть дело? Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 24, 2017 Можно попробовать 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 Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 24, 2017 12 минуты назад, mrgloom сказал: Еще в dice loss есть некий smooth parameter, по идее это же может быть просто что типа eps=1e-3, чтобы не было деления на 0 или это как то влияет на предсказание границ? При изменении данного параметра я никаких сдвигов не увидел. Я использовал 1е-6. 12 минуты назад, mrgloom сказал: Можно попробовать learning rate поменьше имея уже предобученную модель. У меня нет предобученной модели. Или речь идет например о VGG-16? Это возможно сюда прикрутить чтобы не обучаться с ноля? И поможет ли это в данном случае, ведь картинки спутниковые, а ImageNet содержит совсем другие классы. Опять таки почему с BN не работает?) Мало 70 эпох? Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 24, 2017 Имеется ввиду ту модель которую вы уже обучили и которая что то уже выводит. Я говорю с BN там был баг. Выложу в эту репу потом модель resnet'ов которые работают, там как раз были проблемы с BN насколько я помню. https://github.com/mrgloom/kaggle-dogs-vs-cats-solution Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 24, 2017 Та модель, которую обучил - без bn. В keras я пробовал изменять модель после того как обучил. Добавлял слои и загружал веса от старой - так нельзя. В Caffè ведь так же Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 24, 2017 Можно загружать веса и там и там, а вот добавлять потом слои уже сложнее и скорее всего это делается тупо копированием весов из одной модели (из менее короткой в более длинную) в другую. Но изначально я предлагал именно доучить ту же самую модель (с загруженными весами от предыдущего запуска, которые уже что то дают похожее на правду) с меньшим learning rate. Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 25, 2017 В общем через боль, страдания, подбор параметров и еще танцев с бубном проблема решена. Надеюсь кому-то поможет эта информация. Почему-то по умолчанию в 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 отжирается вот так: Если установить CAFFE engine: За одинаковое время обучения сеть с использованием CUDNN engine заврешила 15 эпох. С использованием CAFFE engine 7 эпох. 1 Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 25, 2017 Честно говоря, думал что если caffe собран с включенной cudnn, то он ее будет по умолчанию использовать. А так да, cudnn сильно ускоряет процесс и экономит память. Share this post Link to post Share on other sites
mrgloom 242 Report post Posted August 28, 2017 Раньше в .prototxt нельзя было указывать 'engine' это что то новое, а просто caffe собирается с CUDNN, т.е. это указывается в makefile. Видимо теперь можно собрать с CUDNN, но свитчить engine не перекомпилируя? По дефолту вроде сейфово стоит то что надо https://stackoverflow.com/a/43306411/1179925 По идее и без BN должно работать, на график сходимости интересно посмотреть с и без. Share this post Link to post Share on other sites
prim.ko 3 Report post Posted August 28, 2017 3 часа назад, mrgloom сказал: По идее и без BN должно работать, на график сходимости интересно посмотреть с и без. У меня выборка большая. Настроить BN было принципиально. Не знаю как обстоят дела с caffe, которую собирать ручками, в dockere так. Dice loss прикрутил. Довольно удобно оказалось, что можно юзать python layer. С ним другое дело. Стандартный softmaxwithloss грустно относится к неравномерно распределеным классам. Share this post Link to post Share on other sites