承德网站建设作用,做海报的网站什么编辑,京东商城网站建设分析,七台河网站制作1. 什么是迁移学习 迁移学习(Transfer Learning)是一种机器学习方法#xff0c;就是把为任务 A 开发的模型作为初始点#xff0c;重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务#xff0c;虽然大多数机器学习算法都是… 1. 什么是迁移学习 迁移学习(Transfer Learning)是一种机器学习方法就是把为任务 A 开发的模型作为初始点重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务虽然大多数机器学习算法都是为了解决单个任务而设计的但是促进迁移学习的算法的开发是机器学习社区持续关注的话题。 迁移学习对人类来说很常见例如我们可能会发现学习识别苹果可能有助于识别梨或者学习弹奏电子琴可能有助于学习钢琴。 找到目标问题的相似性迁移学习任务就是从相似性出发将旧领域(domain)学习过的模型应用在新领域上。 2. 为什么需要迁移学习 大数据与少标注的矛盾虽然有大量的数据但往往都是没有标注的无法训练机器学习模型。人工进行数据标定太耗时。大数据与弱计算的矛盾普通人无法拥有庞大的数据量与计算资源。因此需要借助于模型的迁移。普适化模型与个性化需求的矛盾即使是在同一个任务上一个模型也往往难以满足每个人的个性化需求比如特定的隐私设置。这就需要在不同人之间做模型的适配。特定应用如冷启动的需求。 3. 迁移学习的基本问题有哪些 基本问题主要有3个 How to transfer 如何进行迁移学习设计迁移方法What to transfer 给定一个目标领域如何找到相对应的源领域然后进行迁移源领域选择When to transfer 什么时候可以进行迁移什么时候不可以避免负迁移 4. 迁移学习有哪些常用概念 基本定义 域(Domain)数据特征和特征分布组成是学习的主体 源域 (Source domain)已有知识的域目标域 (Target domain)要进行学习的域任务 (Task)由目标函数和学习结果组成是学习的结果 按特征空间分类 同构迁移学习Homogeneous TL 源域和目标域的特征空间相同转存失败重新上传取消 Dₛ Dₜ异构迁移学习Heterogeneous TL源域和目标域的特征空间不同转存失败重新上传取消 Dₛ ! Dₜ 按迁移情景分类 归纳式迁移学习Inductive TL源域和目标域的学习任务不同直推式迁移学习Transductive TL)源域和目标域不同学习任务相同无监督迁移学习Unsupervised TL)源域和目标域均没有标签 按迁移方法分类 基于样本的迁移 (Instance based TL)通过权重重用源域和目标域的样例进行迁移 基于样本的迁移学习方法 (Instance based Transfer Learning) 根据一定的权重生成规则对数据样本进行重用来进行迁移学习。下图形象地表示了基于样本迁移方法的思想源域中存在不同种类的动物如狗、鸟、猫等目标域只有狗这一种类别。在迁移时为了最大限度地和目标域相似我们可以人为地提高源域中属于狗这个类别的样本权重。 基于特征的迁移 (Feature based TL)将源域和目标域的特征变换到相同空间 基于特征的迁移方法 (Feature based Transfer Learning) 是指将通过特征变换的方式互相迁移,来减少源域和目标域之间的差距或者将源域和目标域的数据特征变换到统一特征空间中,然后利用传统的机器学习方法进行分类识别。根据特征的同构和异构性,又可以分为同构和异构迁移学习。下图很形象地表示了两种基于特 征的迁移学习方法。 基于模型的迁移 (Parameter based TL)利用源域和目标域的参数共享模型 基于模型的迁移方法 (Parameter/Model based Transfer Learning) 是指从源域和目标域中找到他们之间共享的参数信息,以实现迁移的方法。这种迁移方式要求的假设条件是 源域中的数据与目标域中的数据可以共享一些模型的参数。下图形象地表示了基于模型的迁移学习方法的基本思想。 转存失败重新上传取消 基于关系的迁移 (Relation based TL)利用源域中的逻辑网络关系进行迁移 基于关系的迁移学习方法 (Relation Based Transfer Learning) 与上述三种方法具有截然不同的思路。这种方法比较关注源域和目标域的样本之间的关系。下图形象地表示了不 同领域之间相似的关系。 转存失败重新上传取消 5. 迁移学习与传统机器学习有什么区别 迁移学习传统机器学习数据分布训练和测试数据不需要同分布训练和测试数据同分布数据标签不需要足够的数据标注足够的数据标注建模可以重用之前的模型每个任务分别建模 6. 迁移学习的核心及度量准则 迁移学习的总体思路可以概括为开发算法来最大限度地利用有标注的领域的知识来辅助目标领域的知识获取和学习。 迁移学习的核心是找到源领域和目标领域之间的相似性并加以合理利用。这种相似性非常普遍。比如不同人的身体构造是相似的自行车和摩托车的骑行方式是相似的国际象棋和中国象棋是相似的羽毛球和网球的打球方式是相似的。这种相似性也可以理解为不变量。以不变应万变才能立于不败之地。 **有了这种相似性后下一步工作就是 如何度量和利用这种相似性。**度量工作的目标有两点一是很好地度量两个领域的相似性不仅定性地告诉我们它们是否相似更定量地给出相似程度。二是以度量为准则通过我们所要采用的学习手段增大两个领域之间的相似性从而完成迁移学习。 一句话总结 相似性是核心度量准则是重要手段。 7. 迁移学习与其他概念的区别 迁移学习与多任务学习关系 多任务学习多个相关任务一起协同学习迁移学习强调信息复用从一个领域(domain)迁移到另一个领域。迁移学习与领域自适应领域自适应使两个特征分布不一致的domain一致。迁移学习与协方差漂移协方差漂移数据的条件概率分布发生变化。 8. 什么情况下可以使用迁移学习 迁移学习最有用的场合是如果你尝试优化任务B的性能通常这个任务数据相对较少。 例如在放射科中你知道很难收集很多射线扫描图来搭建一个性能良好的放射科诊断系统所以在这种情况下你可能会找一个相关但不同的任务如图像识别其中你可能用 1 百万张图片训练过了并从中学到很多低层次特征所以那也许能帮助网络在任务在放射科任务上做得更好尽管任务没有这么多数据。 假如两个领域之间的区别特别的大不可以直接采用迁移学习因为在这种情况下效果不是很好。在这种情况下推荐以上的方法在两个相似度很低的domain之间一步步迁移过去踩着石头过河。 9. 什么是finetune 度网络的finetune也许是最简单的深度网络迁移方法。Finetune,也叫微调、fine-tuning, 是深度学习中的一个重要概念。简而言之finetune就是利用别人己经训练好的网络针对自己的任务再进行调整。从这个意思上看我们不难理解finetune是迁移学习的一部分。 为什么需要已经训练好的网络 在实际的应用中,我们通常不会针对一个新任务,就去从头开始训练一个神经网络。这样的操作显然是非常耗时的。尤其是我们的训练数据不可能像ImageNet那么大可以训练出泛化能力足够强的深度神经网络。即使有如此之多的训练数据,我们从头开始训练,其代价也是不可承受的。 为什么需要 finetune 因为别人训练好的模型,可能并不是完全适用于我们自己的任务。可能别人的训练数据和我们的数据之间不服从同一个分布可能别人的网络能做比我们的任务更多的事情可能别人的网络比较复杂,我们的任务比较简单。 10. 什么是深度网络自适应 深度网络的 finetune 可以帮助我们节省训练时间提高学习精度。但是 finetune 有它的先天不足:它无法处理训练数据和测试数据分布不同的情况。而这一现象在实际应用中比比皆是。因为 finetune 的基本假设也是训练数据和测试数据服从相同的数据分布。这在迁移学习中也是不成立的。因此我们需要更进一步针对深度网络开发出更好的方法使之更好地完成迁移学习任务。 以我们之前介绍过的数据分布自适应方法为参考许多深度学习方法都开发出了自适应层(AdaptationLayer)来完成源域和目标域数据的自适应。自适应能够使得源域和目标域的数据分布更加接近从而使得网络的效果更好。 11. GAN在迁移学习中的应用 生成对抗网络 GAN(Generative Adversarial Nets) 受到自博弈论中的二人零和博弈 (two-player game) 思想的启发而提出。它一共包括两个部分 一部分为生成网络(Generative Network)此部分负责生成尽可能地以假乱真的样本这部分被成为生成器(Generator)另一部分为判别网络(Discriminative Network), 此部分负责判断样本是真实的还是由生成器生成的这部分被成为判别器(Discriminator) 生成器和判别器的互相博弈就完成了对抗训练。 GAN 的目标很明确生成训练样本。这似乎与迁移学习的大目标有些许出入。然而由于在迁移学习中天然地存在一个源领域一个目标领域因此我们可以免去生成样本的过程而直接将其中一个领域的数据 (通常是目标域) 当作是生成的样本。此时生成器的职能发生变化不再生成新样本而是扮演了特征提取的功能不断学习领域数据的特征使得判别器无法对两个领域进行分辨。这样原来的生成器也可以称为特征提取器 (Feature Extractor)。 12. 代码实现 数据下载 Inception-v3模型点击下载 flower_photos数据集点击下载 解压放到images目录下面路径参考下面程序。 import glob
import os.path
import random
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile# Inception-v3模型瓶颈层的节点个数
BOTTLENECK_TENSOR_SIZE 2048# Inception-v3模型中代表瓶颈层结果的张量名称。
# 在谷歌提出的Inception-v3模型中这个张量名称就是pool_3/_reshape:0。
# 在训练模型时可以通过tensor.name来获取张量的名称。
BOTTLENECK_TENSOR_NAME pool_3/_reshape:0# 图像输入张量所对应的名称。
JPEG_DATA_TENSOR_NAME DecodeJpeg/contents:0# 下载的谷歌训练好的Inception-v3模型文件目录
MODEL_DIR ./images/model/# 下载的谷歌训练好的Inception-v3模型文件名
MODEL_FILE tensorflow_inception_graph.pb# 因为一个训练数据会被使用多次所以可以将原始图像通过Inception-v3模型计算得到的特征向量保存在文件中免去重复的计算。
# 下面的变量定义了这些文件的存放地址。
CACHE_DIR ./images/tmp/bottleneck/# 图片数据文件夹。
# 在这个文件夹中每一个子文件夹代表一个需要区分的类别每个子文件夹中存放了对应类别的图片。
INPUT_DATA ./images/flower_photos/# 验证的数据百分比
VALIDATION_PERCENTAGE 10
# 测试的数据百分比
TEST_PERCENTAGE 10# 定义神经网络的设置
LEARNING_RATE 0.01
STEPS 4000
BATCH 100# 这个函数从数据文件夹中读取所有的图片列表并按训练、验证、测试数据分开。
# testing_percentage和validation_percentage参数指定了测试数据集和验证数据集的大小。
def create_image_lists(testing_percentage, validation_percentage):# 得到的所有图片都存在result这个字典(dictionary)里。# 这个字典的key为类别的名称value也是一个字典字典里存储了所有的图片名称。result {}# 获取当前目录下所有的子目录sub_dirs [x[0] for x in os.walk(INPUT_DATA)]# 得到的第一个目录是当前目录不需要考虑is_root_dir Truefor sub_dir in sub_dirs:if is_root_dir:is_root_dir Falsecontinue# 获取当前目录下所有的有效图片文件。extensions [jpg, jpeg, JPG, JPEG]file_list []dir_name os.path.basename(sub_dir)for extension in extensions:file_glob os.path.join(INPUT_DATA, dir_name, *.extension)file_list.extend(glob.glob(file_glob))if not file_list:continue# 通过目录名获取类别的名称。label_name dir_name.lower()# 初始化当前类别的训练数据集、测试数据集和验证数据集training_images []testing_images []validation_images []for file_name in file_list:base_name os.path.basename(file_name)# 随机将数据分到训练数据集、测试数据集和验证数据集。chance np.random.randint(100)if chance validation_percentage:validation_images.append(base_name)elif chance (testing_percentage validation_percentage):testing_images.append(base_name)else:training_images.append(base_name)# 将当前类别的数据放入结果字典。result[label_name] {dir: dir_name,training: training_images,testing: testing_images,validation: validation_images}# 返回整理好的所有数据return result# 这个函数通过类别名称、所属数据集和图片编号获取一张图片的地址。
# image_lists参数给出了所有图片信息。
# image_dir参数给出了根目录。存放图片数据的根目录和存放图片特征向量的根目录地址不同。
# label_name参数给定了类别的名称。
# index参数给定了需要获取的图片的编号。
# category参数指定了需要获取的图片是在训练数据集、测试数据集还是验证数据集。
def get_image_path(image_lists, image_dir, label_name, index, category):# 获取给定类别中所有图片的信息。label_lists image_lists[label_name]# 根据所属数据集的名称获取集合中的全部图片信息。category_list label_lists[category]mod_index index % len(category_list)# 获取图片的文件名。base_name category_list[mod_index]sub_dir label_lists[dir]# 最终的地址为数据根目录的地址 类别的文件夹 图片的名称full_path os.path.join(image_dir, sub_dir, base_name)return full_path# 这个函数通过类别名称、所属数据集和图片编号获取经过Inception-v3模型处理之后的特征向量文件地址。
def get_bottlenect_path(image_lists, label_name, index, category):return get_image_path(image_lists, CACHE_DIR, label_name, index, category) .txt;# 这个函数使用加载的训练好的Inception-v3模型处理一张图片得到这个图片的特征向量。
def run_bottleneck_on_image(sess, image_data, image_data_tensor, bottleneck_tensor):# 这个过程实际上就是将当前图片作为输入计算瓶颈张量的值。这个瓶颈张量的值就是这张图片的新的特征向量。bottleneck_values sess.run(bottleneck_tensor, {image_data_tensor: image_data})# 经过卷积神经网络处理的结果是一个四维数组需要将这个结果压缩成一个特征向量一维数组bottleneck_values np.squeeze(bottleneck_values)return bottleneck_values# 这个函数获取一张图片经过Inception-v3模型处理之后的特征向量。
# 这个函数会先试图寻找已经计算且保存下来的特征向量如果找不到则先计算这个特征向量然后保存到文件。
def get_or_create_bottleneck(sess, image_lists, label_name, index, category, jpeg_data_tensor, bottleneck_tensor):# 获取一张图片对应的特征向量文件的路径。label_lists image_lists[label_name]sub_dir label_lists[dir]sub_dir_path os.path.join(CACHE_DIR, sub_dir)if not os.path.exists(sub_dir_path):os.makedirs(sub_dir_path)bottleneck_path get_bottlenect_path(image_lists, label_name, index, category)# 如果这个特征向量文件不存在则通过Inception-v3模型来计算特征向量并将计算的结果存入文件。if not os.path.exists(bottleneck_path):# 获取原始的图片路径image_path get_image_path(image_lists, INPUT_DATA, label_name, index, category)# 获取图片内容。image_data gfile.FastGFile(image_path, rb).read()# print(len(image_data))# 由于输入的图片大小不一致此处得到的image_data大小也不一致已验证但却都能通过加载的inception-v3模型生成一个2048的特征向量。具体原理不详。# 通过Inception-v3模型计算特征向量bottleneck_values run_bottleneck_on_image(sess, image_data, jpeg_data_tensor, bottleneck_tensor)# 将计算得到的特征向量存入文件bottleneck_string ,.join(str(x) for x in bottleneck_values)with open(bottleneck_path, w) as bottleneck_file:bottleneck_file.write(bottleneck_string)else:# 直接从文件中获取图片相应的特征向量。with open(bottleneck_path, r) as bottleneck_file:bottleneck_string bottleneck_file.read()bottleneck_values [float(x) for x in bottleneck_string.split(,)]# 返回得到的特征向量return bottleneck_values# 这个函数随机获取一个batch的图片作为训练数据。
def get_random_cached_bottlenecks(sess, n_classes, image_lists, how_many, category,jpeg_data_tensor, bottleneck_tensor):bottlenecks []ground_truths []for _ in range(how_many):# 随机一个类别和图片的编号加入当前的训练数据。label_index random.randrange(n_classes)label_name list(image_lists.keys())[label_index]image_index random.randrange(65536)bottleneck get_or_create_bottleneck(sess, image_lists, label_name, image_index, category,jpeg_data_tensor, bottleneck_tensor)ground_truth np.zeros(n_classes, dtypenp.float32)ground_truth[label_index] 1.0bottlenecks.append(bottleneck)ground_truths.append(ground_truth)return bottlenecks, ground_truths# 这个函数获取全部的测试数据。在最终测试的时候需要在所有的测试数据上计算正确率。
def get_test_bottlenecks(sess, image_lists, n_classes, jpeg_data_tensor, bottleneck_tensor):bottlenecks []ground_truths []label_name_list list(image_lists.keys())# 枚举所有的类别和每个类别中的测试图片。for label_index, label_name in enumerate(label_name_list):category testingfor index, unused_base_name in enumerate(image_lists[label_name][category]):# 通过Inception-v3模型计算图片对应的特征向量并将其加入最终数据的列表。bottleneck get_or_create_bottleneck(sess, image_lists, label_name, index, category,jpeg_data_tensor, bottleneck_tensor)ground_truth np.zeros(n_classes, dtype np.float32)ground_truth[label_index] 1.0bottlenecks.append(bottleneck)ground_truths.append(ground_truth)return bottlenecks, ground_truthsdef main(_):# 读取所有图片。image_lists create_image_lists(TEST_PERCENTAGE, VALIDATION_PERCENTAGE)n_classes len(image_lists.keys())# 读取已经训练好的Inception-v3模型。# 谷歌训练好的模型保存在了GraphDef Protocol Buffer中里面保存了每一个节点取值的计算方法以及变量的取值。# TensorFlow模型持久化的问题在第5章中有详细的介绍。with gfile.FastGFile(os.path.join(MODEL_DIR, MODEL_FILE), rb) as f:graph_def tf.GraphDef()graph_def.ParseFromString(f.read())# 加载读取的Inception-v3模型并返回数据输入所对应的张量以及计算瓶颈层结果所对应的张量。bottleneck_tensor, jpeg_data_tensor tf.import_graph_def(graph_def, return_elements[BOTTLENECK_TENSOR_NAME, JPEG_DATA_TENSOR_NAME])# 定义新的神经网络输入这个输入就是新的图片经过Inception-v3模型前向传播到达瓶颈层时的结点取值。# 可以将这个过程类似的理解为一种特征提取。bottleneck_input tf.placeholder(tf.float32, [None, BOTTLENECK_TENSOR_SIZE], nameBottleneckInputPlaceholder)# 定义新的标准答案输入ground_truth_input tf.placeholder(tf.float32, [None, n_classes], nameGroundTruthInput)# 定义一层全连接层来解决新的图片分类问题。# 因为训练好的Inception-v3模型已经将原始的图片抽象为了更加容易分类的特征向量了所以不需要再训练那么复杂的神经网络来完成这个新的分类任务。with tf.name_scope(final_training_ops):weights tf.Variable(tf.truncated_normal([BOTTLENECK_TENSOR_SIZE, n_classes], stddev0.001))biases tf.Variable(tf.zeros([n_classes]))logits tf.matmul(bottleneck_input, weights) biasesfinal_tensor tf.nn.softmax(logits)# 定义交叉熵损失函数cross_entropy tf.nn.softmax_cross_entropy_with_logits(logitslogits, labelsground_truth_input)cross_entropy_mean tf.reduce_mean(cross_entropy)train_step tf.compat.v1.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean)# 计算正确率with tf.name_scope(evaluation):correct_prediction tf.equal(tf.argmax(final_tensor, 1), tf.argmax(ground_truth_input, 1))evaluation_step tf.reduce_mean(tf.cast(correct_prediction, tf.float32))with tf.Session() as sess:tf.global_variables_initializer().run()# 训练过程for i in range(STEPS):# 每次获取一个batch的训练数据train_bottlenecks, train_ground_truth get_random_cached_bottlenecks(sess, n_classes, image_lists, BATCH, training, jpeg_data_tensor, bottleneck_tensor)sess.run(train_step, feed_dict{bottleneck_input: train_bottlenecks, ground_truth_input: train_ground_truth})# 在验证集上测试正确率。if i%100 0 or i1 STEPS:validation_bottlenecks, validation_ground_truth get_random_cached_bottlenecks(sess, n_classes, image_lists, BATCH, validation, jpeg_data_tensor, bottleneck_tensor)validation_accuracy sess.run(evaluation_step, feed_dict{bottleneck_input:validation_bottlenecks, ground_truth_input: validation_ground_truth})print(Step %d: Validation accuracy on random sampled %d examples %.1f%%% (i, BATCH, validation_accuracy*100))# 在最后的测试数据上测试正确率test_bottlenecks, test_ground_truth get_test_bottlenecks(sess, image_lists, n_classes,jpeg_data_tensor, bottleneck_tensor)test_accuracy sess.run(evaluation_step, feed_dict{bottleneck_input: test_bottlenecks,ground_truth_input: test_ground_truth})print(Final test accuracy %.1f%% % (test_accuracy * 100))开始运行
tf.app.run()