1. 程式人生 > >全卷積神經網路FCN-TensorFlow程式碼精析

全卷積神經網路FCN-TensorFlow程式碼精析

這裡解析所有程式碼 並加入詳細註釋

注意事項:

FCN.py


# coding=utf-8
from __future__ import print_function
import tensorflow as tf
import numpy as np

import TensorflowUtils as utils
import read_MITSceneParsingData as scene_parsing
import datetime
import BatchDatsetReader as dataset
from six.moves import xrange

# 引數設定
FLAGS = tf.flags.FLAGS
tf.flags.DEFINE_integer("batch_size", "2", "batch size for training")
tf.flags.DEFINE_string("logs_dir", "logs/", "path to logs directory")
tf.flags.DEFINE_string("data_dir", "Data_zoo/MIT_SceneParsing/", "path to dataset")
tf.flags.DEFINE_float("learning_rate", "1e-6", "Learning rate for Adam Optimizer")
tf.flags.DEFINE_string("model_dir", "Model_zoo/", "Path to vgg model mat")
tf.flags.DEFINE_bool('debug', "True", "Debug mode: True/ False")
tf.flags.DEFINE_string('mode', "train", "Mode train/ test/ visualize")

MODEL_URL = 'http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-19.mat'

MAX_ITERATION = 20000        # 迭代次數
NUM_OF_CLASSESS = 151                # 類別數 151
IMAGE_SIZE = 224                    # 圖片大小 224
fine_tuning = False

# VGG網路部分,weights是權重集合, image是預測影象的向量
def vgg_net(weights, image):
    # VGG網路前五大部分
    layers = (
        'conv1_1', 'relu1_1', 'conv1_2', 'relu1_2', 'pool1',

        'conv2_1', 'relu2_1', 'conv2_2', 'relu2_2', 'pool2',

        'conv3_1', 'relu3_1', 'conv3_2', 'relu3_2', 'conv3_3',
        'relu3_3', 'conv3_4', 'relu3_4', 'pool3',

        'conv4_1', 'relu4_1', 'conv4_2', 'relu4_2', 'conv4_3',
        'relu4_3', 'conv4_4', 'relu4_4', 'pool4',

        'conv5_1', 'relu5_1', 'conv5_2', 'relu5_2', 'conv5_3',
        'relu5_3', 'conv5_4', 'relu5_4'
    )

    net = {}
    current = image     # 預測影象
    for i, name in enumerate(layers):
        kind = name[:4]
        if kind == 'conv':
            kernels, bias = weights[i][0][0][0][0]
            # matconvnet: weights are [width, height, in_channels, out_channels]
            # tensorflow: weights are [height, width, in_channels, out_channels]
            kernels = utils.get_variable(np.transpose(kernels, (1, 0, 2, 3)), name=name + "_w")     # conv1_1_w
            bias = utils.get_variable(bias.reshape(-1), name=name + "_b")       # conv1_1_b
            current = utils.conv2d_basic(current, kernels, bias)        # 前向傳播結果 current
        elif kind == 'relu':
            current = tf.nn.relu(current, name=name)    # relu1_1
            if FLAGS.debug:     # 是否開啟debug模式 true / false
                utils.add_activation_summary(current)       # 畫圖
        elif kind == 'pool':
            # vgg 的前5層的stride都是2,也就是前5層的size依次減小1倍
            # 這裡處理了前4層的stride,用的是平均池化
            # 第5層的pool在下文的外部處理了,用的是最大池化
            # pool1 size縮小2倍
            # pool2 size縮小4倍
            # pool3 size縮小8倍
            # pool4 size縮小16倍
            current = utils.avg_pool_2x2(current)
        net[name] = current     # 每層前向傳播結果放在net中, 是一個字典

    return net


# 預測流程,image是輸入影象,keep_prob dropout比例
def inference(image, keep_prob):
    """
    Semantic segmentation network definition    # 語義分割網路定義
    :param image: input image. Should have values in range 0-255
    :param keep_prob:
    :return:
    """
    # 獲取預訓練網路VGG
    print("setting up vgg initialized conv layers ...")
    # model_dir Model_zoo/
    # MODEL_URL 下載VGG19網址
    model_data = utils.get_model_data(FLAGS.model_dir, MODEL_URL)       # 返回VGG19模型中內容

    mean = model_data['normalization'][0][0][0]                         # 獲得影象均值
    mean_pixel = np.mean(mean, axis=(0, 1))                             # RGB

    weights = np.squeeze(model_data['layers'])                          # 壓縮VGG網路中引數,把維度是1的維度去掉 剩下的就是權重

    processed_image = utils.process_image(image, mean_pixel)            # 影象減均值

    with tf.variable_scope("inference"):                                # 命名作用域 是inference
        image_net = vgg_net(weights, processed_image)                   # 傳入權重引數和預測影象,獲得所有層輸出結果
        conv_final_layer = image_net["conv5_3"]                         # 獲得輸出結果

        pool5 = utils.max_pool_2x2(conv_final_layer)                    # /32 縮小32倍

        W6 = utils.weight_variable([7, 7, 512, 4096], name="W6")        # 初始化第6層的w b
        b6 = utils.bias_variable([4096], name="b6")
        conv6 = utils.conv2d_basic(pool5, W6, b6)
        relu6 = tf.nn.relu(conv6, name="relu6")
        if FLAGS.debug:
            utils.add_activation_summary(relu6)
        relu_dropout6 = tf.nn.dropout(relu6, keep_prob=keep_prob)

        W7 = utils.weight_variable([1, 1, 4096, 4096], name="W7")       # 第7層卷積層
        b7 = utils.bias_variable([4096], name="b7")
        conv7 = utils.conv2d_basic(relu_dropout6, W7, b7)
        relu7 = tf.nn.relu(conv7, name="relu7")
        if FLAGS.debug:
            utils.add_activation_summary(relu7)
        relu_dropout7 = tf.nn.dropout(relu7, keep_prob=keep_prob)

        W8 = utils.weight_variable([1, 1, 4096, NUM_OF_CLASSESS], name="W8")
        b8 = utils.bias_variable([NUM_OF_CLASSESS], name="b8")
        conv8 = utils.conv2d_basic(relu_dropout7, W8, b8)               # 第8層卷積層 分類151類
        # annotation_pred1 = tf.argmax(conv8, dimension=3, name="prediction1")

        # now to upscale to actual image size
        deconv_shape1 = image_net["pool4"].get_shape()                  # 將pool4 1/16結果尺寸拿出來 做融合 [b,h,w,c]
        # 定義反捲積層的 W,B [H, W, OUTC, INC]  輸出個數為pool4層通道個數,輸入為conv8通道個數
        # 擴大兩倍  所以stride = 2  kernel_size = 4
        W_t1 = utils.weight_variable([4, 4, deconv_shape1[3].value, NUM_OF_CLASSESS], name="W_t1")
        b_t1 = utils.bias_variable([deconv_shape1[3].value], name="b_t1")
        # 輸入為conv8特徵圖,使得其特徵圖大小擴大兩倍,並且特徵圖個數變為pool4的通道數
        conv_t1 = utils.conv2d_transpose_strided(conv8, W_t1, b_t1, output_shape=tf.shape(image_net["pool4"]))
        fuse_1 = tf.add(conv_t1, image_net["pool4"], name="fuse_1")     # 進行融合 逐畫素相加

        # 獲得pool3尺寸 是原圖大小的1/8
        deconv_shape2 = image_net["pool3"].get_shape()
        # 輸出通道數為pool3通道數,  輸入通道數為pool4通道數
        W_t2 = utils.weight_variable([4, 4, deconv_shape2[3].value, deconv_shape1[3].value], name="W_t2")
        b_t2 = utils.bias_variable([deconv_shape2[3].value], name="b_t2")
        # 將上一層融合結果fuse_1在擴大兩倍,輸出尺寸和pool3相同
        conv_t2 = utils.conv2d_transpose_strided(fuse_1, W_t2, b_t2, output_shape=tf.shape(image_net["pool3"]))
        # 融合操作deconv(fuse_1) + pool3
        fuse_2 = tf.add(conv_t2, image_net["pool3"], name="fuse_2")

        shape = tf.shape(image)     # 獲得原始影象大小
        # 堆疊列表,反捲積輸出尺寸,[b,原圖H,原圖W,類別個數]
        deconv_shape3 = tf.stack([shape[0], shape[1], shape[2], NUM_OF_CLASSESS])
        # 建立反捲積w[8倍擴大需要ks=16, 輸出通道數為類別個數, 輸入通道數pool3通道數]
        W_t3 = utils.weight_variable([16, 16, NUM_OF_CLASSESS, deconv_shape2[3].value], name="W_t3")
        b_t3 = utils.bias_variable([NUM_OF_CLASSESS], name="b_t3")
        # 反捲積,fuse_2反捲積,輸出尺寸為 [b,原圖H,原圖W,類別個數]
        conv_t3 = utils.conv2d_transpose_strided(fuse_2, W_t3, b_t3, output_shape=deconv_shape3, stride=8)

        # 目前conv_t3的形式為size為和原始影象相同的size,通道數與分類數相同
        # 這句我的理解是對於每個畫素位置,根據第3維度(通道數)通過argmax能計算出這個畫素點屬於哪個分類
        # 也就是對於每個畫素而言,NUM_OF_CLASSESS個通道中哪個數值最大,這個畫素就屬於哪個分類
        # 每個畫素點有21個值,哪個值最大就屬於那一類
        # 返回一張圖,每一個點對於其來別資訊shape=[b,h,w]
        annotation_pred = tf.argmax(conv_t3, dimension=3, name="prediction")
    # 從第三維度擴充套件 形成[b,h,w,c] 其中c=1, conv_t3最後具有21深度的特徵圖
    return tf.expand_dims(annotation_pred, dim=3), conv_t3


def train(loss_val, var_list):
    """

    :param loss_val:  損失函式
    :param var_list:  需要優化的值
    :return:
    """
    optimizer = tf.train.AdamOptimizer(FLAGS.learning_rate)
    grads = optimizer.compute_gradients(loss_val, var_list=var_list)
    if FLAGS.debug:
        # print(len(var_list))
        for grad, var in grads:
            utils.add_gradient_summary(grad, var)
    return optimizer.apply_gradients(grads)     # 返回迭代梯度


def main(argv=None):
    # dropout保留率
    keep_probability = tf.placeholder(tf.float32, name="keep_probabilty")
    # 影象佔坑
    image = tf.placeholder(tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3], name="input_image")
    # 標籤佔坑
    annotation = tf.placeholder(tf.int32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 1], name="annotation")

    # 預測一個batch影象  獲得預測圖[b,h,w,c=1]  結果特徵圖[b,h,w,c=151]
    pred_annotation, logits = inference(image, keep_probability)
    tf.summary.image("input_image", image, max_outputs=2)
    tf.summary.image("ground_truth", tf.cast(annotation, tf.uint8), max_outputs=2)
    tf.summary.image("pred_annotation", tf.cast(pred_annotation, tf.uint8), max_outputs=2)
    # 空間交叉熵損失函式[b,h,w,c=151]  和labels[b,h,w]    每一張圖分別對比
    loss = tf.reduce_mean((tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,
                                                                          labels=tf.squeeze(annotation, squeeze_dims=[3]),
                                                                          name="entropy")))
    tf.summary.scalar("entropy", loss)

    # 返回需要訓練的變數列表
    trainable_var = tf.trainable_variables()
    if FLAGS.debug:
        for var in trainable_var:
            utils.add_to_regularization_and_summary(var)

    # 傳入損失函式和需要訓練的變數列表
    train_op = train(loss, trainable_var)

    print("Setting up summary op...")
    # 生成繪圖資料
    summary_op = tf.summary.merge_all()

    print("Setting up image reader...")
    # data_dir = Data_zoo/MIT_SceneParsing/
    # training: [{image: 圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [{}][{}]
    train_records, valid_records = scene_parsing.read_dataset(FLAGS.data_dir)
    print(len(train_records))   # 長度
    print(len(valid_records))

    print("Setting up dataset reader")
    image_options = {'resize': True, 'resize_size': IMAGE_SIZE}
    if FLAGS.mode == 'train':
        # 讀取圖片 產生類物件 其中包含所有圖片資訊
        train_dataset_reader = dataset.BatchDatset(train_records, image_options)
    validation_dataset_reader = dataset.BatchDatset(valid_records, image_options)

    sess = tf.Session()

    print("Setting up Saver...")
    saver = tf.train.Saver()
    summary_writer = tf.summary.FileWriter(FLAGS.logs_dir, sess.graph)

    sess.run(tf.global_variables_initializer())
    # logs/
    if fine_tuning:
        ckpt = tf.train.get_checkpoint_state(FLAGS.logs_dir)    # 訓練斷點回復
        if ckpt and ckpt.model_checkpoint_path:                 # 如果存在checkpoint檔案 則恢復sess
            saver.restore(sess, ckpt.model_checkpoint_path)
            print("Model restored...")

    if FLAGS.mode == "train":
        for itr in range(MAX_ITERATION):
            # 讀取下一batch
            train_images, train_annotations = train_dataset_reader.next_batch(FLAGS.batch_size)
            feed_dict = {image: train_images, annotation: train_annotations, keep_probability: 0.85}

            # 迭代優化需要訓練的變數
            sess.run(train_op, feed_dict=feed_dict)

            if itr % 10 == 0:
                # 迭代10次列印顯示
                train_loss, summary_str = sess.run([loss, summary_op], feed_dict=feed_dict)
                print("Step: %d, Train_loss:%g" % (itr, train_loss))
                summary_writer.add_summary(summary_str, itr)

            if itr % 500 == 0:
                # 迭代500 次驗證
                valid_images, valid_annotations = validation_dataset_reader.next_batch(FLAGS.batch_size)
                valid_loss = sess.run(loss, feed_dict={image: valid_images, annotation: valid_annotations,
                                                       keep_probability: 1.0})
                print("%s ---> Validation_loss: %g" % (datetime.datetime.now(), valid_loss))
                # 儲存模型
                saver.save(sess, FLAGS.logs_dir + "model.ckpt", itr)

    elif FLAGS.mode == "visualize":
        # 視覺化
        valid_images, valid_annotations = validation_dataset_reader.get_random_batch(FLAGS.batch_size)
        # pred_annotation預測結果圖
        pred = sess.run(pred_annotation, feed_dict={image: valid_images, annotation: valid_annotations,
                                                    keep_probability: 1.0})
        valid_annotations = np.squeeze(valid_annotations, axis=3)
        pred = np.squeeze(pred, axis=3)

        for itr in range(FLAGS.batch_size):
            utils.save_image(valid_images[itr].astype(np.uint8), FLAGS.logs_dir, name="inp_" + str(5+itr))
            utils.save_image(valid_annotations[itr].astype(np.uint8), FLAGS.logs_dir, name="gt_" + str(5+itr))
            utils.save_image(pred[itr].astype(np.uint8), FLAGS.logs_dir, name="pred_" + str(5+itr))
            print("Saved image: %d" % itr)


if __name__ == "__main__":
    tf.app.run()

read_MITSceneParsingData.py

# coding=utf-8
__author__ = 'charlie'
import numpy as np
import os
import random
from six.moves import cPickle as pickle
from tensorflow.python.platform import gfile
import glob

import TensorflowUtils as utils

# DATA_URL = 'http://sceneparsing.csail.mit.edu/data/ADEChallengeData2016.zip'
DATA_URL = 'http://data.csail.mit.edu/places/ADEchallenge/ADEChallengeData2016.zip'


def read_dataset(data_dir):
    # data_dir = Data_zoo / MIT_SceneParsing /
    pickle_filename = "MITSceneParsing.pickle"
    # 檔案路徑  Data_zoo / MIT_SceneParsing / MITSceneParsing.pickle
    pickle_filepath = os.path.join(data_dir, pickle_filename)
    if not os.path.exists(pickle_filepath):
        utils.maybe_download_and_extract(data_dir, DATA_URL, is_zipfile=True)       # 不存在檔案 則下載
        SceneParsing_folder = os.path.splitext(DATA_URL.split("/")[-1])[0]          # ADEChallengeData2016
        # result =   {training: [{image: 圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [][]
        #            validation:[{image:圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [] []}
        result = create_image_lists(os.path.join(data_dir, SceneParsing_folder))    # Data_zoo / MIT_SceneParsing / ADEChallengeData2016
        print ("Pickling ...")      # 製作pickle檔案
        with open(pickle_filepath, 'wb') as f:
            pickle.dump(result, f, pickle.HIGHEST_PROTOCOL)
    else:
        print ("Found pickle file!")

    with open(pickle_filepath, 'rb') as f:      # 開啟pickle檔案
        result = pickle.load(f)                 # 讀取
        training_records = result['training']
        validation_records = result['validation']
        del result
    # training: [{image: 圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [{}][{}]
    return training_records, validation_records


def create_image_lists(image_dir):
    """

    :param image_dir:   Data_zoo / MIT_SceneParsing / ADEChallengeData2016
    :return:
    """
    if not gfile.Exists(image_dir):
        print("Image directory '" + image_dir + "' not found.")
        return None
    directories = ['training', 'validation']
    image_list = {}     # 影象字典   training:[]  validation:[]

    for directory in directories:       # 訓練集和驗證集 分別製作
        file_list = []
        image_list[directory] = []
        # Data_zoo/MIT_SceneParsing/ADEChallengeData2016/images/training/*.jpg
        file_glob = os.path.join(image_dir, "images", directory, '*.' + 'jpg')
        # 加入檔案列表  包含所有圖片檔案全路徑+檔名字  如 Data_zoo/MIT_SceneParsing/ADEChallengeData2016/images/training/hi.jpg
        file_list.extend(glob.glob(file_glob))

        if not file_list:   # 檔案為空
            print('No files found')
        else:
            for f in file_list:     # 掃描檔案列表   這裡f對應檔案全路徑
                # 獲取圖片名字 hi
                filename = os.path.splitext(f.split("/")[-1])[0]
                # Data_zoo/MIT_SceneParsing/ADEChallengeData2016/annotations/training/*.png
                annotation_file = os.path.join(image_dir, "annotations", directory, filename + '.png')
                if os.path.exists(annotation_file):     # 如果檔案路徑存在
                    #  image:圖片全路徑, annotation:標籤全路徑, filename:圖片名字
                    record = {'image': f, 'annotation': annotation_file, 'filename': filename}
                    # image_list{training:[{image:圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [] []
                    #            validation:[{image:圖片全路徑, annotation:標籤全路徑, filename:圖片名字}] [] []}
                    image_list[directory].append(record)
                else:
                    print("Annotation file not found for %s - Skipping" % filename)
        # 對圖片列表進行洗牌
        random.shuffle(image_list[directory])
        no_of_images = len(image_list[directory])   # 包含圖片檔案的個數
        print ('No. of %s files: %d' % (directory, no_of_images))

    return image_list

TensorflowUitls.py

# coding=utf-8
__author__ = 'Charlie'
# Utils used with tensorflow implemetation
import tensorflow as tf
import numpy as np
import scipy.misc as misc
import os, sys
from six.moves import urllib
import tarfile
import zipfile
import scipy.io


# 獲取VGG預訓練模型
def get_model_data(dir_path, model_url):
    # model_dir Model_zoo/
    # MODEL_URL 下載VGG19網址
    maybe_download_and_extract(dir_path, model_url)     # 判斷檔案目錄和檔案是否存在, 不存在則下載
    filename = model_url.split("/")[-1]                 # 將url按/切分, 取最後一個字串作為檔名
    filepath = os.path.join(dir_path, filename)         # dir_path/filename     檔案全路徑
    if not os.path.exists(filepath):                    # 判斷是否存在此檔案
        raise IOError("VGG Model not found!")
    data = scipy.io.loadmat(filepath)                   # 使用io讀取VGG.mat檔案
    return data


def maybe_download_and_extract(dir_path, url_name, is_tarfile=False, is_zipfile=False):
    # dir_path Model_zoo/
    # url_name 下載VGG19網址
    if not os.path.exists(dir_path):        # 判斷檔案路徑是否存在,如果不存在則建立此路徑
        os.makedirs(dir_path)
    filename = url_name.split('/')[-1]      # 將url中 按照/切分,並取最後一個字串 作為檔名字
    filepath = os.path.join(dir_path, filename)     # 檔案路徑 = dir_path/filename
    if not os.path.exists(filepath):         # 判斷此路徑是否存在(此檔案),如果不存在,則下載
        def _progress(count, block_size, total_size):       # 內部函式
            sys.stdout.write(
                '\r>> Downloading %s %.1f%%' % (filename, float(count * block_size) / float(total_size) * 100.0))
            sys.stdout.flush()

        filepath, _ = urllib.request.urlretrieve(url_name, filepath, reporthook=_progress)    # 將url中檔案 下載到filepath路徑中
        print()
        statinfo = os.stat(filepath)
        print('Succesfully downloaded', filename, statinfo.st_size, 'bytes.')
        if is_tarfile:          # 如果是tar檔案, 解壓縮
            tarfile.open(filepath, 'r:gz').extractall(dir_path)
        elif is_zipfile:        # 如果是zip檔案 解壓縮
            with zipfile.ZipFile(filepath) as zf:
                zip_dir = zf.namelist()[0]
                zf.extractall(dir_path)

BatchDatsetReader.py

# coding=utf-8
"""
Code ideas from https://github.com/Newmu/dcgan and tensorflow mnist dataset reader
"""
import numpy as np
import scipy.misc as misc


class BatchDatset:
    files = []
    images = []
    annotations = []
    image_options = {}
    batch_offset = 0
    epochs_completed = 0

    def __init__(self, records_list, image_options={}):
        """
        Intialize a generic file reader with batching for list of files
        :param records_list: list of file records to read -
        sample record: {'image': f, 'annotation': annotation_file, 'filename': filename}
        :param image_options: A dictionary of options for modifying the output image
        Available options:
        resize = True/ False
        resize_size = #size of output image - does bilinear resize
        color=True/False
        """
        print("Initializing Batch Dataset Reader...")
        print(image_options)
        self.files = records_list       # 檔案列表
        self.image_options = image_options  # 圖片操作方式 resize  224
        self._read_images()

    def _read_images(self):
        self.__channels = True
        # 掃描files字典中所有image 圖片全路徑
        # 根據檔案全路徑讀取影象,並將其擴充為RGB格式
        self.images = np.array([self._transform(filename['image']) for filename in self.files])
        self.__channels = False

        # 掃描files字典中所有annotation 圖片全路徑
        # 根據檔案全路徑讀取影象,並將其擴充為三通道格式
        self.annotations = np.array(
            [np.expand_dims(self._transform(filename['annotation']), axis=3) for filename in self.files])
        print (self.images.shape)
        print (self.annotations.shape)

    def _transform(self, filename):
        # 讀取檔案圖片
        image = misc.imread(filename)
        if self.__channels and len(image.shape) < 3:  # make sure images are of shape(h,w,3)
            # 將圖片三個通道設定為一樣的圖片
            image = np.array([image for i in range(3)])

        if self.image_options.get("resize", False) and self.image_options["resize"]:

            resize_size = int(self.image_options["resize_size"])
            # 使用最近鄰插值法resize圖片
            resize_image = misc.imresize(image,
                                         [resize_size, resize_size], interp='nearest')
        else:
            resize_image = image

        return np.array(resize_image)       # 返回已經resize的圖片

    def get_records(self):
        """
        返回圖片和標籤全路徑
        :return:
        """
        return self.images, self.annotations

    def reset_batch_offset(self, offset=0):
        """
        剩下的batch
        :param offset:
        :return:
        """
        self.batch_offset = offset

    def next_batch(self, batch_size):
        # 當前第幾個batch
        start = self.batch_offset
        # 讀取下一個batch  所有offset偏移量+batch_size
        self.batch_offset += batch_size
        # iamges儲存所有圖片資訊 images.shape(len, h, w)
        if self.batch_offset > self.images.shape[0]:      # 如果下一個batch的偏移量超過了圖片總數 說明完成了一個epoch
            # Finished epoch
            self.epochs_completed += 1      # epochs完成總數+1
            print("****************** Epochs completed: " + str(self.epochs_completed) + "******************")
            # Shuffle the data
            perm = np.arange(self.images.shape[0])      # arange生成陣列(0 - len-1) 獲取圖片索引
            np.random.shuffle(perm)         # 對圖片索引洗牌
            self.images = self.images[perm]     # 洗牌之後的圖片順序
            self.annotations = self.annotations[perm]
            # Start next epoch
            start = 0           # 下一個epoch從0開始
            self.batch_offset = batch_size  # 已完成的batch偏移量

        end = self.batch_offset             # 開始到結束self.batch_offset   self.batch_offset+batch_size
        return self.images[start:end], self.annotations[start:end]      # 取出batch

    def get_random_batch(self, batch_size):
        # 按照一個batch_size一個塊  進行對所有圖片總數進行隨機操作, 相當於洗牌工作
        indexes = np.random.randint(0, self.images.shape[0], size=[batch_size]).tolist()
        return self.images[indexes], self.annotations[indexes]

相關推薦

神經網路FCN-TensorFlow程式碼

這裡解析所有程式碼 並加入詳細註釋注意事項:FCN.py# coding=utf-8 from __future__ import print_function import tensorflow as tf import numpy as np import Tensor

神經網路FCN詳解(附帶Tensorflow詳解程式碼實現)

一.導論 在影象語義分割領域,困擾了電腦科學家很多年的一個問題則是我們如何才能將我們感興趣的物件和不感興趣的物件分別分割開來呢?比如我們有一隻小貓的圖片,怎樣才能夠通過計算機自己對影象進行識別達到將小貓和圖片當中的背景互相分割開來的效果呢?如下圖所示:      而在2015年

使用神經網路FCN,進行影象語義分割詳解(附程式碼實現)

一.導論 在影象語義分割領域,困擾了電腦科學家很多年的一個問題則是我們如何才能將我們感興趣的物件和不感興趣的物件分別分割開來呢?比如我們有一隻小貓的圖片,怎樣才能夠通過計算機自己對影象進行識別達到將小貓和圖片當中的背景互相分割開來的效果呢?如下圖所示:      而在2015年

深度學習筆記(基礎)——(六)神經網路FCN

    通常CNN在卷積層之後會接上若干個全連線層,將卷積層產生的特徵圖(Feature Map)對映成一個固定長度的特徵向量進行分類。以AlexNet為代表的經典CNN結構適合於影象級的分類和迴歸任務,因為它們最後都期望得到整個輸入影象的一個數值描述,如AlexN

影象語義分割(1)-FCN:用於語義分割的神經網路

論文地址:Fully Convolutional Networks for Semantic Segmentation [Long J , Shelhamer E , Darrell T . Fully Convolutional Networks for Semantic Segmen

10分鐘看懂神經網路FCN ):語義分割深度模型先驅

大家好,我是為人造的智慧操碎了心的智慧禪師。今天是10月24日,既是程式設計師節,也是程式設計師

FCN神經網路

原文連結: http://mp.weixin.qq.com/s?__biz=MzI1NTE4NTUwOQ==&mid=2650324665&idx=1&sn=3022e7e75a4bad0acdde36fe3edf565e&scene=5&a

DeepLearning tutorial(4)CNN神經網路原理簡介+程式碼詳解

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

lesson26-27神經網路,lenet5程式碼講解

https://www.bilibili.com/video/av22530538/?p=27   ##mnist_lenet5_forward.py #encoding:utf-8 import tensorflow as tf IMAGE_SIZE = 28 NUM_CHANN

神經網路tensorflow實現

版權宣告:本文為博主原創文章,未經博主允許不得轉載。    https://blog.csdn.net/happyhorizion/article/details/77894047 卷積神經網路概述 一般一個卷積神經網路由多個卷積層構成,在卷基層內部通常會有如下幾個操作: 1

deeplearning.ai 第四課第一週, 神經網路tensorflow實現

1、載入需要模組和函式: import math import numpy as np import h5py import matplotlib.pyplot as plt import scipy from PIL import Image from

神經網路影象分割(U-net)-keras實現

最近在研究全卷積神經網路在影象分割方面的應用,因為自己是做醫學影象處理方面的工作,所以就把一個基於FCN(全卷積神經網路)的神經網路用 keras 實現了,並且用了一個醫學影象的資料集進行了影象分割。 全卷積神經網路 大名鼎鼎的FCN就不多做介紹了,這裡有一篇很好的博文 http://www.c

基於神經網路tensorflow實現的人臉識別

以前在學習卷積神經網路的時候,發現了很多很有趣的demo,有一次發現了上面這個人臉識別的例子,不過當時還看不懂,經過一段時間之後決定試試能不能將上面的例子改一下,調以調參什麼的,於是就有了這篇文章。本以為我的程式碼和原文沒有什麼太大的區別,應該不會出現什麼錯誤,但是實際自己上

Alexnet 神經網路 純 matlab程式碼 底層實現(一)正向傳播

本程式的主要目的是通過自主編寫alexnet網路,深入瞭解卷積、pooling、區域性區域正則化、全連線層、基於動量的隨機梯度下降、卷積神經網路的引數修正演算法等神經網路的基礎知識。 寫這個部落格一方面幫助自己理清思路,另一方面督促自己加快進度,也希望可以幫助到同樣想深入瞭

卷積神經網路入門一種全卷積神經網路(LeNet),從左至右依次為卷積→子取樣→卷積→子取樣→連線→連線→高斯連線測試 最後,為了檢驗 CNN 能否工作,我們準備不同的另一組圖片與標記集(不能在訓練

轉載來自:http://blog.csdn.net/maweifei/article/details/52443995 第一層——數學部分 CNN 的第一層通常是卷積層(Convolutional Layer)。輸入內容為一個 32 x 32 x 3 的畫素值陣列。現在

深度學習——神經網路tensorflow框架下的應用案例

一、簡單的卷積神經網路的小應用 tensorflow框架下構建訓練一個簡單的3層卷積神經網路實現分類問題 (一)資料集介紹——SIGNS Datasets 教電腦破譯手語,在白色的牆壁前拍照,得到以下資料集。 現在的任務是建立一個演算法,使有語音障礙的人與不懂手語的人

神經網路CNN:Tensorflow實現(以及對特徵的視覺化)

本文主要是實現了一個簡單的卷積神經網路,並對卷積過程中的提取特徵進行了視覺化.   卷積神經網路最早是為了解決影象識別的問題,現在也用在時間序列資料和文字資料處理當中,卷積神經網路對於資料特徵的提取不用額外進行,在對網路的訓練的過程當中,網路會自動提

深度學習筆記:神經網路Tensorflow實現

在上一講中,我們學習瞭如何利用 numpy 手動搭建卷積神經網路。但在實際的影象識別中,使用 numpy 去手寫 CNN 未免有些吃力不討好。在 DNN 的學習中,我們也是在手動搭建之後利用 Tensorflow 去重新實現一遍,一來為了能夠對神經網路的傳播機制能夠理

神經網路tensorflow實現

tensorflow中集成了很多庫和函式,卷積神經網路的實現變得十分簡單,這節講述如何利用tensorflow實現一個兩個卷積層的神經網路,用於對手寫數字的識別。 程式碼如下: # -*- coding:utf-8 -*- #功能:使用卷積神經網路實現對手寫數字的識別

CNN神經網路原理簡介+程式碼詳解

到這裡,CNN的基本”構件“都有了,下面要用這些”構件“組裝成LeNet5(當然,是簡化的,上面已經說了),具體來說,就是組裝成:LeNet5=input+LeNetConvPoolLayer_1+LeNetConvPoolLayer_2+HiddenLayer+LogisticRegression+ou