Глубокое обучение — одна из самых горячих тем в области искусственного интеллекта в последние годы, но в прошлом для того, чтобы играть в глубокое обучение, в дополнение к превосходным навыкам программирования также требовались массивные данные и мощное оборудование. Однако появление таких фреймворков, как TensorFlow и Keras, значительно снизило сложность программирования, а идея трансферного обучения также позволяет использовать существующие модели с небольшим объемом данных и временем обучения для достижения хороших результатов.
В этой статье будет продемонстрировано, как использовать трансферное обучение для обучения модели, которая может классифицировать различные виды цветов по изображениям, и может достичь точности более 80% для пяти видов цветов (на 60% выше, чем слепой Мэн), и для этого требуется только An обычный домашний компьютер может завершить процесс обучения.
Что такое трансферное обучение
Человеческий разум может применять знания и опыт, полученные в одной области, в других подобных областях. Таким образом, при столкновении с новой ситуацией, если ситуация больше похожа на предыдущий опыт, тем быстрее можно приобрести знания в этой области. Традиционный метод машинного обучения будет рассматривать разные задачи как совершенно независимые, например, модель распознавания кошек.Если в обучающей выборке все картинки дневные, то обученную модель можно использовать для задачи распознавания кошек ночью. плохо. Передача обучения вдохновлена этим, пытаясь перенести модель изисходная задачаЗнания, полученные на нем, передаютсяцелевая задачав приложении.
Например, исходной задачей может быть идентификация транспортного средства на картинке, а целевой задачей может быть идентификация грузовика, идентификация легкового автомобиля, идентификация автобуса и т. д. Разумное использование трансферного обучения позволяет избежать обучения модели отдельно для каждой целевой задачи, что значительно экономит вычислительные ресурсы.
Кроме того, трансферное обучение — это не конкретная модель машинного обучения, а скорее метод оптимизации. Вообще говоря, задачи машинного обучения требуют, чтобы тестовый и обучающий наборы имели одинаковое распределение вероятностей, однако в некоторых случаях часто не хватает целевых наборов данных, достаточно больших, чтобы удовлетворить конкретную обучающую задачу. Трансферное обучение предполагает, что мы можем выполнить определенный объем обучения на общем большом наборе данных, а затем использовать целевой небольшой набор данных для дальнейшего усиления обучения.
В следующем примере показано, как перенести глубокую сверточную сеть для распознавания изображений, VGG, на новую задачу распознавания типов цветов.В исходной задаче VGG может распознавать только цветы, но передача обучения позволяет модели не только распознавать цветы. цветок, а также определить конкретный вид цветка.
Представляем ВГГ
VGG — модель-победитель конкурса ILSVRC в поле зрения в 2014 году с частотой ошибок 7,3% в наборе данных ImageNet, что значительно побило мировой рекорд предыдущего года в 11,7%. VGG16 в основном наследует AlexNetглубокийидеи и двигаться вперед, чтобы достичьГлубже. AlexNet использует только 8-уровневую сеть, в то время как две версии VGG представляют собой 16-уровневую сетевую версию и 19-уровневую сетевую версию. В следующей практике трансферного обучения мы будем использовать немного более простой VGG16, который имеет почти такую же точность, как VGG19, но быстрее.
Структурная схема VGG выглядит следующим образом:
Формат входных данных VGG - данные пикселей 244 * 224 * 3. После серии сверточных нейронных сетей и обработки объединенных сетей выходные данные представляют собой 4096-мерные данные признаков, а затем через трехуровневую полносвязную обработку нейронной сети, и, наконец, результаты классификации получаются путем нормализации softmax.
Модель VGG16 может пройтиСкачать здесь(пароль 78g9), модель представляет собой файл .npy, который по сути представляет собой огромный объект numpy, содержащий все параметры модели VGG16.Файл имеет размер около 500 МБ, поэтому видно, что обучение таких модель с нуля, с помощью идеи трансферного обучения мы можем напрямую обучаться на основе этой модели.
Далее мы немного объясним о сверточных нейронных сетях и сетях объединения:
Сверточная нейронная сеть
Сверточные нейронные сети особенно используются в данных изображения.В отличие от обычных полносвязных нейронных сетей, которые требуют тренировочных весов между любыми двумя узлами в верхнем и нижнем слоях сети, каждый слой сверточной сети обучает только несколько объемов. следующий слой сети-это свертка выходных данных предыдущего слоя.Поэтому многослойная сверточная нейронная сеть преобразует данные тонкого изображения в меньший, но более толстый массив, как показано ниже
Сверточные нейронные сети обладают хорошей статистической инвариантностью, и каждый слой может обучаться разным уровням знаний. Например, первый уровень научится распознавать простые формы на изображениях, такие как линии и сплошные цветные блоки. А более поздние слои будут подниматься до более высоких уровней абстракции, таких как формы, компоненты объектов, пока весь объект не будет распознан.
Если визуализировать изображение активированных нейронов в сверточной нейронной сети, то мы получим следующие результаты: Во-первых, первый слой может идентифицировать некоторые диагональные и цветовые границы.
Затем сеть второго уровня может изучить некоторые более сложные понятия, такие как круги и полосы.
Третий уровень изучает некоторые простые объекты, такие как шины и лица.
На более высоких уровнях сверточные нейронные сети способны идентифицировать все более сложные объекты, и этот процесс также очень согласуется с процессом распознавания объектов человеком, то есть от простых паттернов ко все более сложным паттернам.
Максимальное объединение и выпадение
Как максимальный пул, так и выпадение являются широко используемыми методами в сверточных нейронных сетях. Их принципы очень просты. Максимальный пул — это фильтр, который выбирает максимальное значение в области в соответствии с определенным размером шага в качестве репрезентативного значения для этой области. Как показано ниже:
Одним из преимуществ этого является то, что он позволяет нейронной сети сосредоточиться на наиболее важных элементах, уменьшая размер входных элементов.
Выпадение — это случайное отбрасывание значения входного признака в соответствии с вероятностью.Цель этого — заставить нейронную сеть поддерживать определенную степень избыточности в процессе обучения, чтобы обученная модель была более стабильной и не легко переобуваться.
Набор данных распознавания цветов
Набор данных цветов, который мы собираемся использовать, можно найти здесь.скачать.
Набор данных содержит следующие данные:
вид цветка | Количество картинок (шт.) |
---|---|
daisy | 633 |
dandelion | 898 |
roses | 641 |
sunflowers | 699 |
tulips | 799 |
передача практики обучения
Получив предварительные знания, мы можем приступить к созданию собственной сети распознавания цветов.
Во-первых, мы передаем все изображения в VGG16 и используем слой сверточной сети с пятью раундами и слой пула в структуре глубокой сети VGG16, чтобы получить 4096-мерный вектор признаков для каждого изображения, а затем мы напрямую используем этот признак. вместо вектора Исходное изображение плюс несколько слоев полностью связанных нейронных сетей обучаются на наборе данных цветов.
Поэтому, по сути, мы используем VGG16 в качестве экстрактора признаков изображения, а затем выполняем на этой основе обычное обучение нейронной сети, так что исходные данные измерения 244*224*3 преобразуются в 4096 измерений, и каждый объем информации в одно измерение значительно улучшено, что значительно снижает потребление вычислительных ресурсов и реализует применение знаний, полученных при обучении распознаванию объектов, к специальным задачам классификации цветов.
файловая структура
Для более удобного использования сети VGG мы можем напрямую использовать модуль загрузки VGG, предоставленный tensorflow, который можно найти вСкачать здесь.
Сначала убедитесь, что в рабочем каталоге, где работает код или блокнот Jupyter, есть цветок.фотографии, тензорный потокvgg Эти две папки представляют собой набор данных цветов и тензорный поток.vgg, затем скопируйте ранее загруженный VGG16 в tensorflowпапка вгг.
├── transfer_learning.py(运行代码)
├── flower_phtots
│ ├── daisy
│ ├── dandelion
│ ├── roses
│ └── ...
└── tensorflow_vgg
├── vgg16.py
├── vgg16.npy
└── ...
Затем импортируйте необходимые модули Python
import os
import numpy as np
import tensorflow as tf
from tensorflow_vgg import vgg16
from tensorflow_vgg import utils
Загрузите набор данных распознавания цветов
Далее мы загружаем в него все картинки цветов из папки flower_photos, а в качестве значения метки используем подпапку, где находятся картинки.
data_dir = 'flower_photos/'
contents = os.listdir(data_dir)
classes = [each for each in contents if os.path.isdir(data_dir + each)]
Собственные значения, рассчитанные с помощью VGG16
# 首先设置计算batch的值,如果运算平台的内存越大,这个值可以设置得越高
batch_size = 10
# 用codes_list来存储特征值
codes_list = []
# 用labels来存储花的类别
labels = []
# batch数组用来临时存储图片数据
batch = []
codes = None
with tf.Session() as sess:
# 构建VGG16模型对象
vgg = vgg16.Vgg16()
input_ = tf.placeholder(tf.float32, [None, 224, 224, 3])
with tf.name_scope("content_vgg"):
# 载入VGG16模型
vgg.build(input_)
# 对每个不同种类的花分别用VGG16计算特征值
for each in classes:
print("Starting {} images".format(each))
class_path = data_dir + each
files = os.listdir(class_path)
for ii, file in enumerate(files, 1):
# 载入图片并放入batch数组中
img = utils.load_image(os.path.join(class_path, file))
batch.append(img.reshape((1, 224, 224, 3)))
labels.append(each)
# 如果图片数量到了batch_size则开始具体的运算
if ii % batch_size == 0 or ii == len(files):
images = np.concatenate(batch)
feed_dict = {input_: images}
# 计算特征值
codes_batch = sess.run(vgg.relu6, feed_dict=feed_dict)
# 将结果放入到codes数组中
if codes is None:
codes = codes_batch
else:
codes = np.concatenate((codes, codes_batch))
# 清空数组准备下一个batch的计算
batch = []
print('{} images processed'.format(ii))
Таким образом, мы можем получить массив кодов и массив меток, в которых хранятся значения характеристик и категории всех цветов соответственно.
Эти два массива можно сохранить на диск с помощью следующего кода:
with open('codes', 'w') as f:
codes.tofile(f)
import csv
with open('labels', 'w') as f:
writer = csv.writer(f, delimiter='\n')
writer.writerow(labels)
Подготовьте обучающий набор, проверочный набор и тестовый набор
Тщательное обучение модели должно включать проверку и тестирование. Сначала я заменил категориальные метки в массиве меток на One Hot Encode.
from sklearn.preprocessing import LabelBinarizer
lb = LabelBinarizer()
lb.fit(labels)
labels_vecs = lb.transform(labels)
Следующим шагом является извлечение данных, поскольку объем данных для разных типов цветов не совсем одинаков, а данные в массиве labels не перетасовывались, поэтому наиболее подходящим методом является использование метода StratifiedShuffleSplit для выполнения иерархического случайное деление. Предположим, мы используем обучающий набор: набор проверки: набор тестов = 8:1:1, тогда код выглядит следующим образом:
from sklearn.model_selection import StratifiedShuffleSplit
ss = StratifiedShuffleSplit(n_splits=1, test_size=0.2)
train_idx, val_idx = next(ss.split(codes, labels))
half_val_len = int(len(val_idx)/2)
val_idx, test_idx = val_idx[:half_val_len], val_idx[half_val_len:]
train_x, train_y = codes[train_idx], labels_vecs[train_idx]
val_x, val_y = codes[val_idx], labels_vecs[val_idx]
test_x, test_y = codes[test_idx], labels_vecs[test_idx]
print("Train shapes (x, y):", train_x.shape, train_y.shape)
print("Validation shapes (x, y):", val_x.shape, val_y.shape)
print("Test shapes (x, y):", test_x.shape, test_y.shape)
В это время, если мы выведем размерность данных, мы должны получить следующие результаты:
Train shapes (x, y): (2936, 4096) (2936, 5)
Validation shapes (x, y): (367, 4096) (367, 5)
Test shapes (x, y): (367, 4096) (367, 5)
обучать сеть
После разделения набора данных мы можем начать обучение набора данных Предположим, мы используем 256-мерный полносвязный слой, 5-мерный полносвязный слой (потому что мы хотим классифицировать пять разных типов цветов) и слой softmax. Конечно, структура сети здесь может быть изменена произвольно, и вы можете продолжать пробовать другие структуры, чтобы найти подходящую.
# 输入数据的维度
inputs_ = tf.placeholder(tf.float32, shape=[None, codes.shape[1]])
# 标签数据的维度
labels_ = tf.placeholder(tf.int64, shape=[None, labels_vecs.shape[1]])
# 加入一个256维的全连接的层
fc = tf.contrib.layers.fully_connected(inputs_, 256)
# 加入一个5维的全连接层
logits = tf.contrib.layers.fully_connected(fc, labels_vecs.shape[1], activation_fn=None)
# 计算cross entropy值
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=labels_, logits=logits)
# 计算损失函数
cost = tf.reduce_mean(cross_entropy)
# 采用用得最广泛的AdamOptimizer优化器
optimizer = tf.train.AdamOptimizer().minimize(cost)
# 得到最后的预测分布
predicted = tf.nn.softmax(logits)
# 计算准确度
correct_pred = tf.equal(tf.argmax(predicted, 1), tf.argmax(labels_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
Для удобного разделения данных на пакеты для уменьшения использования памяти можно также использовать функцию для создания пакетов.
def get_batches(x, y, n_batches=10):
""" 这是一个生成器函数,按照n_batches的大小将数据划分了小块 """
batch_size = len(x)//n_batches
for ii in range(0, n_batches*batch_size, batch_size):
# 如果不是最后一个batch,那么这个batch中应该有batch_size个数据
if ii != (n_batches-1)*batch_size:
X, Y = x[ii: ii+batch_size], y[ii: ii+batch_size]
# 否则的话,那剩余的不够batch_size的数据都凑入到一个batch中
else:
X, Y = x[ii:], y[ii:]
# 生成器语法,返回X和Y
yield X, Y
Теперь вы можете запустить обучение,
# 运行多少轮次
epochs = 20
# 统计训练效果的频率
iteration = 0
# 保存模型的保存器
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for e in range(epochs):
for x, y in get_batches(train_x, train_y):
feed = {inputs_: x,
labels_: y}
# 训练模型
loss, _ = sess.run([cost, optimizer], feed_dict=feed)
print("Epoch: {}/{}".format(e+1, epochs),
"Iteration: {}".format(iteration),
"Training loss: {:.5f}".format(loss))
iteration += 1
if iteration % 5 == 0:
feed = {inputs_: val_x,
labels_: val_y}
val_acc = sess.run(accuracy, feed_dict=feed)
# 输出用验证机验证训练进度
print("Epoch: {}/{}".format(e, epochs),
"Iteration: {}".format(iteration),
"Validation Acc: {:.4f}".format(val_acc))
# 保存模型
saver.save(sess, "checkpoints/flowers.ckpt")
тестовая сеть
Следующим шагом является использование тестового набора для проверки эффекта модели.
with tf.Session() as sess:
saver.restore(sess, tf.train.latest_checkpoint('checkpoints'))
feed = {inputs_: test_x,
labels_: test_y}
test_acc = sess.run(accuracy, feed_dict=feed)
print("Test accuracy: {:.4f}".format(test_acc))
В конце концов я получил точность 88,83% на своем компьютере, вы можете продолжить настройку размера пакета или структуры модели, чтобы получить лучший результат.
Для этой фотографии одуванчика с семизвездной божьей коровкой
Прогнозируемые значения, данные моделью, следующие:
Видно, что эффект модели довольно стабилен, а наше время расчета во всем процессе составляет всего более 30 минут, в чем прелесть трансферного обучения.
P.S
Конечно, другие фреймворки глубокого обучения также могут легко реализовать трансферное обучение, например здесь.Код КерасаРеализован классификатор переноса VGG для определения пород собак примерно в 20 линиях.
использованная литература
- A Survey on Transfer Learning[IE, о, исследуйте.IEEE.org/document/52…]
- Обучение переносу распознавания цветов Tensorflowwoohoo.tensorflow.org/tutorials/i…
- сеть VGGАР Вест V.org/PDF/1409.15…
- Визуализация сверточных нейронных сетейWoohoo. Мэтью вор dick.com/pubs/AR West VE…
- Глубокое обучение UdaictyТалант U big city.com/course/deep…