Базовый процесс обучения модели с помощью TensorFlow

Python искусственный интеллект машинное обучение TensorFlow

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

Основной процесс использования TensorFlow

В этой статье будет представлен основной процесс обучения моделей с использованием tensorflow, включая создание и чтение TFRecords, обучение и сохранение моделей, а также чтение моделей.

Подготовить

TFRecord

TensorFlow предоставляет единый формат для хранения данных, это формат TFRecord.

message Example {  
 Features features = 1;  
};  
  
message Features{  
 map<string,Feature> featrue = 1;  
};  
  
message Feature{  
    oneof kind{  
        BytesList bytes_list = 1;  
        FloatList float_list = 2;  
        Int64List int64_list = 3;  
    }  
};  

Как видно из кода, tf.train.Example содержит словарь, ключ которого — строка, а значение — Feature, Feature может быть строкой (BytesList), списком чисел с плавающей запятой (FloatList), целым списком A чисел (Int64List).

Написание TFRecord обычно делится на три этапа:

  • Чтение данных, которые необходимо преобразовать
  • Преобразуйте данные в пример буфера протокола и напишите эту структуру данных.
  • После преобразования данных в строку запишите их через TFRecordWriter

метод первый

На этот раз наши данные хранятся в нескольких папках, поэтому самый прямой способ прочитать данные — просмотреть все файлы в каталоге, а затем прочитать и записать файлы TFRecord. Этот метод соответствует файлуMakeTFRecord.py, давайте посмотрим на код ключа

    filenameTrain = 'TFRecord/train.tfrecords'
    filenameTest = 'TFRecord/test.tfrecords'
    writerTrain = tf.python_io.TFRecordWriter(filenameTrain)
    writerTest = tf.python_io.TFRecordWriter(filenameTest)
    folders = os.listdir(HOME_PATH)
    for subFoldersName in folders:
        label = transform_label(subFoldersName)
        path = os.path.join(HOME_PATH, subFoldersName)  # 文件夹路径
        subFoldersNameList = os.listdir(path)
        i = 0
        for imageName in subFoldersNameList:
            imagePath = os.path.join(path, imageName)
            images = cv2.imread(imagePath)
            res = cv2.resize(images, (128, 128), interpolation=cv2.INTER_CUBIC)
            image_raw_data = res.tostring()
            example = tf.train.Example(features=tf.train.Features(feature={
                'label': _int64_feature(label),
                'image_raw': _bytes_feature(image_raw_data)
            }))
            if i <= len(subFoldersNameList) * 3 / 4:
                writerTrain.write(example.SerializeToString())
            else:
                writerTest.write(example.SerializeToString())
            i += 1

При выполнении данных я планирую использовать 3/4 данных в качестве обучающего набора, а оставшуюся 1/4 данных в качестве тестового набора.Для удобства я сохраню его в виде двух файлов.

Основной процесс состоит в том, чтобы просмотреть все папки в каталоге Fnt, затем войти в подпапки, чтобы просмотреть файлы изображений в каталоге, а затем использовать OpenCV.imreadМетод считывает его, а затем преобразует данные изображения в строку. `_bytes_feature' хранит строки в структуре данных, предоставляемой TFRecord.

Приведенное выше изображение было успешно прочитано и записано в структуру данных TFRecord, а как насчет метки, соответствующей изображению?

def transform_label(folderName):
    label_dict = {
        'Sample001': 0,
        'Sample002': 1,
        'Sample003': 2,
        'Sample004': 3,
        'Sample005': 4,
        'Sample006': 5,
        'Sample007': 6,
        'Sample008': 7,
        'Sample009': 8,
        'Sample010': 9,
        'Sample011': 10,
    }
    return label_dict[folderName]

Я создал словарь.Поскольку изображения в файле имеют один и тот же тип, отношение сопоставления создается между именем папки, соответствующей изображению, и соответствующей ему меткой. в кодеlabel = transform_label(subFoldersName)Полученная этим методом метка изображения.

Способ второй

При использовании данных, сгенерированных методом 1, для обучения модели вы обнаружите, что их очень легко переобучить. Потому что, когда мы читаем данные, мы упаковываем их в пакеты и считываем, хотя мы можем использоватьtf.train.shuffle_batchМетод шифрует данные в очереди, а затем считывает их, но, поскольку в классе слишком много данных, он приведет к тому, что данные останутся в том же классе даже после шифрования. Например: число 0 имеет образцы 1000. Предположим, вы прочитали очередь до 1000, поэтому даже если изображение будет зашифровано после чтения очереди, оно все равно будет 0. Это склонно к переобучению во время обучения. Чтобы этого не произошло, моя идея состоит в том, чтобы перетасовать картинку и записать ее при выполнении данных. соответствующий файлMakeTFRecord2.py, код ключа выглядит следующим образом

    folders = os.listdir(HOME_PATH)
    for subFoldersName in folders:
        path = os.path.join(HOME_PATH, subFoldersName)  # 文件夹路径
        subFoldersNameList = os.listdir(path)
        for imageName in subFoldersNameList:
            imagePath = os.path.join(path, imageName)
            totalList.append(imagePath)

    # 产生一个长度为图片总数的不重复随机数序列
    dictlist = random.sample(range(0, len(totalList)), len(totalList))  
    print(totalList[0].split('\\')[1].split('-')[0])    # 这是图片对应的类别

    i = 0
    for path in totalList:
        images = cv2.imread(totalList[dictlist[i]])
        res = cv2.resize(images, (128, 128), interpolation=cv2.INTER_CUBIC)
        image_raw_data = res.tostring()
        label = transform_label(totalList[dictlist[i]].split('\\')[1].split('-')[0])
        print(label)
        example = tf.train.Example(features=tf.train.Features(feature={
            'label': _int64_feature(label),
            'image_raw': _bytes_feature(image_raw_data)
        }))
        if i <= len(totalList) * 3 / 4:
            writerTrain.write(example.SerializeToString())
        else:
            writerTest.write(example.SerializeToString())
        i += 1

Основной процесс: просмотреть все изображения в каталоге и добавить их путь в большой список. Контролируйте, какое изображение используется неповторяющейся последовательностью случайных чисел. Это достигает случайных целей.

Как получить теги? файлы изображений类型-序号Названный в этой форме, здесь получается类型Имя, установите словарь для создания отношения сопоставления.

def transform_label(imgType):
    label_dict = {
        'img001': 0,
        'img002': 1,
        'img003': 2,
        'img004': 3,
        'img005': 4,
        'img006': 5,
        'img007': 6,
        'img008': 7,
        'img009': 8,
        'img010': 9,
        'img011': 10,
    }
    return label_dict[imgType]

Полноразмерное изображение CNN

вести перепискуCNN_train.pyдокумент
Как читать данные TFRecord во время обучения, обратитесь к следующему коду

# 读训练集数据
def read_train_data():
    reader = tf.TFRecordReader()
    filename_train = tf.train.string_input_producer(["TFRecord128/train.tfrecords"])
    _, serialized_example_test = reader.read(filename_train)
    features = tf.parse_single_example(
        serialized_example_test,
        features={
            'label': tf.FixedLenFeature([], tf.int64),
            'image_raw': tf.FixedLenFeature([], tf.string),
        }
    )

    img_train = features['image_raw']
    images_train = tf.decode_raw(img_train, tf.uint8)
    images_train = tf.reshape(images_train, [128, 128, 3])
    labels_train = tf.cast(features['label'], tf.int64)
    labels_train = tf.cast(labels_train, tf.int64)
    labels_train = tf.one_hot(labels_train, 10)
    return images_train, labels_train

пройти черезfeatures[键名]способ чтения сохраненных данных, имя ключа и тип данных должны соответствовать записанным данным.

Что касается сверточной нейронной сети здесь, я написал ее со ссылкой на код обучения Ван Сюэчана. Конечно, копирование определенно невозможно, и будет ситуация с потерей NaN, Мое решение - скопировать его.AlexNetВ , слой LRN добавляется после свертки для нормализации локального отклика. При настройке параметров добавьте постоянный термин l2. Код ключа выглядит следующим образом

def weights_with_loss(shape, stddev, wl):
    var = tf.truncated_normal(stddev=stddev, shape=shape)
    if wl is not None:
        weight_loss = tf.multiply(tf.nn.l2_loss(var), wl, name='weight_loss')
        tf.add_to_collection('losses', weight_loss)
    return tf.Variable(var)

def net(image, drop_pro):
    W_conv1 = weights_with_loss([5, 5, 3, 32], 5e-2, wl=0.0)
    b_conv1 = biasses([32])
    conv1 = tf.nn.relu(conv(image, W_conv1) + b_conv1)
    pool1 = max_pool_2x2(conv1)
    norm1 = tf.nn.lrn(pool1, 4, bias=1, alpha=0.001 / 9.0, beta=0.75)

    W_conv2 = weights_with_loss([5, 5, 32, 64], stddev=5e-2, wl=0.0)
    b_conv2 = biasses([64])
    conv2 = tf.nn.relu(conv(norm1, W_conv2) + b_conv2)
    norm2 = tf.nn.lrn(conv2, 4, bias=1, alpha=0.001 / 9.0, beta=0.75)
    pool2 = max_pool_2x2(norm2)

    W_conv3 = weights_with_loss([5, 5, 64, 128], stddev=0.04, wl=0.004)
    b_conv3 = biasses([128])
    conv3 = tf.nn.relu(conv(pool2, W_conv3) + b_conv3)
    pool3 = max_pool_2x2(conv3)

    W_conv4 = weights_with_loss([5, 5, 128, 256], stddev=1 / 128, wl=0.004)
    b_conv4 = biasses([256])
    conv4 = tf.nn.relu(conv(pool3, W_conv4) + b_conv4)
    pool4 = max_pool_2x2(conv4)

    image_raw = tf.reshape(pool4, shape=[-1, 8 * 8 * 256])

    # 全连接层
    fc_w1 = weights_with_loss(shape=[8 * 8 * 256, 1024], stddev=1 / 256, wl=0.0)
    fc_b1 = biasses(shape=[1024])
    fc_1 = tf.nn.relu(tf.matmul(image_raw, fc_w1) + fc_b1)

    # drop-out层
    drop_out = tf.nn.dropout(fc_1, drop_pro)

    fc_2 = weights_with_loss([1024, 10], stddev=0.01, wl=0.0)
    fc_b2 = biasses([10])

    return tf.matmul(drop_out, fc_2) + fc_b2

128x128x3Процесс обучения оригинальному изображению

128*128
Правильная ставка на проверочном наборе
128v
128 используется здесь1283 картинки, картинки относительно большие, поэтому у меня возникла идея. При выполнении данных TFRecord уменьшите вдвое размер изображения. Итак, есть второй способ.

Размер изображения уменьшился вдвое CNN

соответствующий файлCNN_train2.py
Единственное отличие от вышеописанного метода — размер изображения.128*128*3изменился на64*64*3Поэтому я не буду повторяться здесь.
64x64x3процесс обучения изображения

64*64
Правильная ставка на проверочном наборе
64v

сохранить модель

существуетCNN_train.py, код, соответствующий сохранению модели,

def save_model(sess, step):
    MODEL_SAVE_PATH = "./model128/"
    MODEL_NAME = "model.ckpt"
    saver = tf.train.Saver()
    saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=step)

save_model(sess, i)

i- количество итераций, и его соответствующие параметры могут быть опущеныglobal_step

Проверьте точность на тестовом наборе

соответствующий файлAccuracyTest.py
Код в основном такой же, как код обучения, вот как восстановить модель. ключевой код

    ckpt = tf.train.get_checkpoint_state(MODEL_PATH)
    if ckpt and ckpt.model_checkpoint_path:
        #加载模型
        saver.restore(sess, ckpt.model_checkpoint_path)

Стоит упомянуть, чтоtf.train.get_checkpoint_stateЭтот метод автоматически найдет модель с наибольшим количеством итераций в папке и прочитает ее. а такжеsaver.restore(sess, ckpt.model_checkpoint_path)Метод восстановит переменные параметры последней итерации модели во время обучения.

Просмотрите прочитанное изображение TFRecord

соответствующий файлReadTest.py
Если вы хотите проверить правильность обработки изображения при создании TFRecord, проще всего отобразить изображение. Код ключа выглядит следующим образом

def plot_images(images, labels):
    for i in np.arange(0, 20):
        plt.subplot(5, 5, i + 1)
        plt.axis('off')
        plt.title(labels[i], fontsize=14)
        plt.subplots_adjust(top=1.5)
        plt.imshow(images[i])
    plt.show()

plot_images(image, label
Пример

Суммировать

В процессе исследования я столкнулся со многими проблемами.Благодаря терпеливой помощи старшего Вана, я надеюсь, что эта статья поможет большему количеству людей. Я новичок в дороге, если я ошибаюсь, поправьте меня, спасибо.

Код загружен на гитхаб:GitHub.com/мы обычно обжариваем/десятки…

читать оригинал