Использование трансферного обучения с EfficientNet и MobileNetV2
В этой статье я покажу вам, как создать классификацию рентгеновских изображений вируса Covide 19 с использованием трансферного обучения, а сеть будет основана на серии EfficientNet, которая достигла высочайшего уровня точности в ImageNet, будучи В 8,4 раза меньше и в 6,1 раза быстрее. И модель MobileNetV2… есть больше ссылок на MobileNetv2, вы можете прочитать это
весь код в google colab
Что такое Covid -19?
Коронавирусы - это группа вирусов, которые могут вызывать заболевания, от простуды и кашля до иногда более серьезных заболеваний. Ближневосточный респираторный синдром (БВРС-КоВ) и ТОРС-КоВ были тяжелыми случаями, с которыми мир уже столкнулся. SARS-CoV-2 (n-коронавирус) - это новый вирус семейства коронавирусов, впервые обнаруженный в 2019 году и ранее не обнаруженный у людей. Это стойкий вирус, который появился в Ухане в декабре 2019 года. Позднее Всемирная организация здравоохранения объявила его пандемией из-за высокой распространенности во всем мире. В настоящее время (15 мая 2020 г.) это приводит к 300 000 смертей по всему миру, в том числе 159 000 смертей только в Европе. Становится важным понять этот разброс. Здесь мы объясняем важность глубокого обучения в области компьютерного зрения в проблеме классификации этих изображений и знания, какая модель является лучшей по точности.
зачем переносить обучение?
В этом посте вы узнаете, как классифицировать изображения Covide-19, а также виртуальные и нормальные изображения здоровья легких человека с помощью трансферного обучения из предварительно обученной сети. Предварительно обученная модель - это сохраненная сеть, которая ранее была обучен на большом наборе данных, как правило, на крупномасштабной задаче классификации изображений. Вы можете либо использовать предварительно обученную модель как есть, либо использовать трансферное обучение, чтобы настроить эту модель для конкретной задачи. Интуиция, лежащая в основе трансферного обучения для классификации изображений, заключается в том, что если модель обучается на большом и достаточно общем наборе данных, эта модель будет эффективно работать. служат общей моделью визуального мира. Затем вы можете воспользоваться преимуществами этих изученных карт функций, не начинать с нуля, обучив большую модель на большом наборе данных.
Набор данных из kaggle
Что за болваны?
Kaggle - это платформа, на которой можно соревноваться с другими в соревнованиях, основанных на задачах машинного обучения. Возможно, вы знаете о Codechef, Hackerrank и т. Д., Kaggle тоже похож на них, но ключевое отличие состоит в том, что конкуренция связана только с машинным обучением, наукой о данных, глубоким обучением или искусственным интеллектом. Большую часть времени вам давали набор данных для обучения и тестирования для создания хороших моделей машинного обучения, и когда вы публикуете свое ядро, другие проверят его, а затем отдадут вам голоса, как Quora.
Почему EfficientNet?
По сравнению с другими моделями, обеспечивающими аналогичную точность ImageNet, EfficientNet намного меньше по размеру. Например, модель ResNet50 имеет в общей сложности 23 534 592 параметра, и даже несмотря на то, что она все еще не справляется с наименьшей эффективностью сети, которая в сумме принимает всего 5 330 564 параметра. Почему она настолько эффективна? Чтобы ответить на этот вопрос, мы углубимся в его базовую модель и строительный блок. Возможно, вы слышали о строительном блоке классической модели ResNet - это блок идентификации и свертки. Для EfficientNet его основным строительным блоком является мобильное перевернутое узкое место MBConv, которое впервые было представлено в MobileNetV2. За счет использования ярлыков непосредственно между узкими местами, которые соединяют гораздо меньшее количество каналов по сравнению с слоями расширения, в сочетании с разделимой по глубине сверткой, которая эффективно сокращает вычисления почти в k2 раз по сравнению с традиционными слоями. Где k обозначает размер ядра, определяя высоту и ширину окна двумерной свертки.
и вы можете видеть, начиная с самой маленькой конфигурации EfficientNet B0 и заканчивая самой большой B7, точность неуклонно возрастает при сохранении относительно небольшого размера.
Передача обучения с EfficientNet и MobileNetV2
Трансферное обучение для классификации изображений более или менее не зависит от модели. Вы можете выбрать любую другую предварительно обученную модель ImageNet, такую как MobileNetV2 или ResNet50, в качестве замены, если хотите. Предварительно обученная сеть - это просто сохраненная сеть, предварительно обученная на большом наборе данных, таком как ImageNet. Изученные функции могут оказаться полезными для множества различных задач компьютерного зрения, даже если эти новые задачи могут включать в себя классы, совершенно отличные от классов исходной задачи. EfficientNet построен для классификации ImageNet и содержит 1000 меток классов. Для нашего набора данных у нас только 2. Это означает, что последние несколько слоев для классификации нам не нужны. Их можно исключить при загрузке модели, указав для аргумента include_top значение False, и это относится и к другим моделям ImageNet, доступным в приложениях Keras. Мы ожидаем, что модель будет хорошо работать в нашем наборе данных Covide19-X Ray для ее классификации. если он обнаруживает, что чьи-то легкие инфицированы Covid-19 или не инфицированы по изображениям рентгеновского сканирования. Проблема классификации Covid-19 X Ray с относительно небольшим количеством образцов, самый простой способ начать - открыть этот блокнот в Colab, в то время как я объясню более подробную информацию здесь, в этом посте. Сначала перейдите на сайт kaggle и скопируйте api к набору данных. Конечно, у вас должна быть учетная запись в сервисах kaggle… .Перейдите по этой ссылке для набора данных за пределами
и скопируйте команду api для набора данных
О наборе данных
Классификационная маркировка базы данных для рентгеновских снимков грудной клетки была создана для трех случаев, классифицированных как случаи COVID-19, в дополнение к обычным изображениям и изображениям вирусной пневмонии. Есть 219 положительных изображений COVID-19, 1341 нормальных изображений и 1345 изображений вирусной пневмонии.
Хорошо, скопируйте эту команду API с изображения выше
kaggle datasets download -d tawsifurrahman/covid19-radiography-database
В блокноте google colab команда будет
!kaggle datasets download -d awsifurrahman/covid19-radiography-database
и напишите эту команду
from google.colab import files files.upload() !ls -lha kaggle.json !pip install -q kaggle !mkdir -p ~/.kaggle !cp kaggle.json ~/.kaggle/ !chmod 600 ~/.kaggle/kaggle.json !kaggle datasets download -d awsifurrahman/covid19-radiography-database # unzip folder dataset !unzip /content/covid19-radiography-database.zip
для отображения некоторых изображений из набора данных
#load images def show_images(dataset_path): # size of the image: 48*48 pixels pic_size = 48 # input path for the images base_path = dataset_path plt.figure(0, figsize=(12,20)) #cpt = 0 for expression in os.listdir(base_path + "/"): for i in range(25): # cpt = cpt + 1 plt.subplot(5,5,i+1) img = load_img(base_path + "/" + expression + "/" +os.listdir(base_path + "/" + expression)[i], target_size=(pic_size, pic_size)) plt.imshow(img, cmap="gray") plt.tight_layout() plt.show()
Установите EfficientNet
#pip command install EfficientNet model by using !pip install efficientnet
Импортированные библиотеки и модули
#Imported libraries and modules import efficientnet.keras as efn from sklearn.metrics import classification_report,accuracy_score,f1_score,confusion_matrix import numpy as np from keras.preprocessing.image import load_img, img_to_array import matplotlib.pyplot as plt import os from keras.models import Model from keras.utils import np_utils import tensorflow as tf from tensorflow.keras.models import load_model from keras.utils.np_utils import to_categorical from keras.preprocessing.image import ImageDataGenerator from keras.layers import Activation,Dense, Dropout, Flatten, Conv2D from keras.layers import GlobalAveragePooling2D,BatchNormalization
загрузка предварительно обученной базовой модели конверсии
img_shape=224 import efficientnet.keras as efn #using here EfficientNet series BO baseModel =efn.EfficientNetB0(weights ='noisy-student', include_top=False, input_shape = (img_shape,img_shape,3)) baseModel.summary()
Чтобы создать наш собственный стек слоев классификации поверх сверточной базовой модели EfficientNet. Адаптируем GlobalAveragePooling2D. GlobalMaxPooling2D дает гораздо меньшее количество функций по сравнению со слоем Flatten, что эффективно уменьшает количество параметров.
x = baseModel.output x = GlobalAveragePooling2D()(x) x = Dropout(0.3)(x) x = Dense(128, activation=”relu”)(x) x = Dropout(0.3)(x) x = Dense(64, activation=”relu”)(x) predictions = Dense(3, activation=”softmax”)(x) model = Model(inputs=baseModel.input, outputs=predictions) for layer in baseModel.layers: layer.trainable = False
вы можете скомпилировать и обучить модель с помощью Keras ImageDataGenerator, который добавляет различные параметры увеличения данных во время обучения, чтобы снизить вероятность переобучения.
data_gen= ImageDataGenerator( horizontal_flip=True, vertical_flip=True, rotation_range=90, width_shift_range=0.1, height_shift_range=0.1, zoom_range=.1, rescale=1/255, fill_mode=’nearest’, shear_range=0.1, brightness_range=[0.5, 1.5], validation_split=0.3)
Обратите внимание, что данные проверки не следует дополнять!
test_datagen = ImageDataGenerator(rescale=1.0 / 255) train_generator = train_datagen.flow_from_directory( # This is the target directory train_dir, # All images will be resized to target height and width. target_size=(height, width), batch_size=batch_size, # Since we use categorical_crossentropy loss, we need categorical labels class_mode=”categorical”, ) validation_generator = test_datagen.flow_from_directory( validation_dir, target_size=(height, width), batch_size=batch_size, class_mode=”categorical”, )
Затем вы можете снова скомпилировать и обучить модель еще для нескольких эпох.
model.compile(optimizer='adam', loss="categorical_crossentropy", metrics=['accuracy'])
окончательная подгонка модели
results = model.fit(train_generator,epochs=epochs,steps_per_epoch=train_generator.n/batch_size,validation_data=val_generator,validation_steps=val_generator.n/batch_size)
Таким образом, мы можем создать функцию для предварительно обученной эффективной модели для каждой модели от B0 до B7 для тестирования всех этих моделей в нашем наборе данных
def model_efficientnetb0(no_classes): #mport Model img_shape=224 import efficientnet.keras as efn model =efn.EfficientNetB0(weights ='noisy-student', include_top=False, input_shape = (img_shape,img_shape,3)) x = model.output x = GlobalAveragePooling2D()(x) x = Dropout(0.3)(x) x = Dense(128, activation="relu")(x) x = Dropout(0.3)(x) x = Dense(64, activation="relu")(x) predictions = Dense(no_classes, activation="softmax")(x) model = Model(inputs=model.input, outputs=predictions) return model def model_efficientnetb7(no_classes): #mport Model img_shape=600 model =efn.EfficientNetB7(weights ='imagenet', include_top=False, input_shape = (img_shape,img_shape,3)) x = model.output x = GlobalAveragePooling2D()(x) x = Dropout(0.3)(x) x = Dense(128, activation="relu")(x) x = Dropout(0.3)(x) x = Dense(64, activation="relu")(x) predictions = Dense(no_classes, activation="softmax")(x) model = Model(inputs=model.input, outputs=predictions) return model
мы можем увидеть сводку для модели
no_classes=3 model=model_efficientnetb0(no_classes) model.summary()
а также встроил все это в функцию
def model_train(dataset_path,model_name,epochs,batch_size,no_class,img_shape): show_images(dataset_path) no_classes=no_class data_gen= ImageDataGenerator( horizontal_flip=True, vertical_flip=True, rotation_range=90, width_shift_range=0.1, height_shift_range=0.1, zoom_range=.1, rescale=1/255, fill_mode='nearest', shear_range=0.1, brightness_range=[0.5, 1.5], validation_split=0.3) #load the training data train_generator = data_gen.flow_from_directory( dataset_path, target_size=(img_shape,img_shape), batch_size=batch_size,class_mode='categorical', subset='training',shuffle=True) #load the training data val_suffle=False val_generator = data_gen.flow_from_directory(dataset_path, target_size=(img_shape,img_shape),batch_size=batch_size, class_mode='categorical',subset='validation',shuffle=val_suffle) train_generator.next()[0].shape,train_generator.next()[1].shape val_generator.next()[0].shape,val_generator.next()[1].shape x,y = train_generator.next() plt.figure(figsize=(10,10)) for i in range(8): plt.subplot(4,2,i+1) image = x[i] label = y[i] print (label) plt.imshow(image) plt.show() if model_name=='efficientnetb0': model=model_efficientnetb0(no_classes) if model_name=='efficientnetb7': model=model_efficientnetb7(no_classes) model.compile(optimizer='adam', loss="categorical_crossentropy", metrics=['accuracy']) results = model.fit(train_generator,epochs=epochs,steps_per_epoch=train_generator.n/batch_size, validation_data=val_generator,validation_steps=val_generator.n/batch_size) no_epochs=int(epochs) plt.plot(results.history['accuracy']) plt.plot(results.history['val_accuracy']) plt.title(model_name+' Model Accuracy ') plt.ylabel('accuracy') plt.xlabel('epoch') plt.legend(['train', 'test'], loc='upper left') plt.savefig(model_name+'_accuracy.png') plt.show() plt.savefig(model_name+'_accuracy.png') plt.plot(results.history['loss']) plt.plot(results.history['val_loss']) plt.title(model_name+' Model Loss') plt.ylabel('loss') plt.xlabel('epoch') plt.legend(['train', 'test'], loc='upper left') plt.savefig(model_name+'_loss.png') plt.show() plt.savefig(model_name+'_loss.png') val_generator.reset() pred=model.predict_generator(val_generator,steps=val_generator.n/batch_size,verbose=1) predicted_class_indices=np.argmax(pred,axis=1) labels = (train_generator.class_indices) labels = dict((v,k) for k,v in labels.items()) y_pred=model.predict(val_generator,steps=val_generator.n/batch_size,verbose=1) y_true = val_generator.classes y_pred=np.argmax(y_pred, axis=1) from sklearn.metrics import classification_report,accuracy_score,f1_score print('accuracy_score:',accuracy_score(y_true,y_pred)) print('f1_score:',f1_score(y_true,y_pred,average='macro')) class_label=list(train_generator.class_indices.keys()) print(classification_report(y_true, _pred,target_names=class_label)) class_names = val_generator.class_indices.keys() #save model model.save(model_name+'.h5')
и вычислите значение precision_score для набора данных проверки и прогноза
val_generator.reset() pred=model.predict_generator(val_generator,steps=val_generator.n/batch_size,verbose=1) predicted_class_indices=np.argmax(pred,axis=1) labels = (train_generator.class_indices) labels = dict((v,k) for k,v in labels.items()) y_pred=model.predict(val_generator,steps=val_generator.n/batch_size,verbose=1) y_true = val_generator.classes y_pred=np.argmax(y_pred, axis=1) from sklearn.metrics import classification_report,accuracy_score,f1_score print('accuracy_score:',accuracy_score(y_true,y_pred)) print('f1_score:',f1_score(y_true,y_pred,average='macro'))
Окончательная модель прогнозирования и тестирование для невидимого набора данных
def model_predict(img_path, model_path): MODEL_PATH = model_path print('Model loading...') model=load_model(MODEL_PATH) print('Model loaded. Started serving...') image = cv2.imread(img_path) image = cv2.resize(image, (img_shape,img_shape)) #image = image.astype("float") / 255.0 image = img_to_array(image) image = np.expand_dims(image, axis=0) proba = model.predict(image) confidence = proba.max() * 100 print('Class Name:',proba) print('Confidence:',confidence)
и, наконец, вы можете протестировать другую серию моделей effectiveneXX, используя
dataset_path='/content/COVID-19 Radiography Database' model_name='efficientnetb0' epochs=10 batch_size=48 no_class=3 img_shape=224 model_train(dataset_path,model_name, epochs,batch_size,no_class,img_shape)
precision recall f1-score support COVID-19 0.68 1.00 0.81 65 NORMAL 0.97 0.87 0.92 402 Viral Pneumonia 0.93 0.96 0.94 403 accuracy 0.92 870 macro avg 0.86 0.94 0.89 870 weighted avg 0.93 0.92 0.92 870
используя другую модель для MobileNetV2
dataset_path='/content/COVID-19 Radiography Database' model_name='mobilenetv2' epochs=10 batch_size=16 no_class=3 img_shape=224
Результат для MobileNetV2
precision recall f1-score support COVID-19 0.90 0.72 0.80 65 NORMAL 0.98 0.33 0.49 402 Viral Pneumonia 0.59 1.00 0.74 403 accuracy 0.67 870 macro avg 0.82 0.68 0.68 870 weighted avg 0.79 0.67 0.63 870
Матрица неточностей для показателей (неточность, точность, матрица отзыва)
Нормализовать матрицу неточностей
получить случайный пакет изображений и спрогнозировать изображения на модели
Результат
мы видим, что Efficientnet B0 лучше и лучше MobileNetV2
по размеру параметров и точности для них обоих.
весь код в google colab
Ссылки
[1] https://www.dlology.com/blog/transfer-learning-with-efficientnet/
[2] Kaggle
[3] https://arxiv.org/abs/1905.11946
[4] https://www.kaggle.com/tawsifurrahman/covid19-radiography-database