这篇文章主要围绕TensorFlow中卷积的自定义填充和tensorflow卷积操作展开,旨在为您提供一份详细的参考资料。我们将全面介绍TensorFlow中卷积的自定义填充的优缺点,解答tensor
这篇文章主要围绕TensorFlow中卷积的自定义填充和tensorflow卷积操作展开,旨在为您提供一份详细的参考资料。我们将全面介绍TensorFlow中卷积的自定义填充的优缺点,解答tensorflow卷积操作的相关问题,同时也会为您带来Effective TensorFlow Chapter 4: TensorFlow中的广播Broadcast机制【转】、python-在Tensorflow中将自定义渐变定义为类方法、Tensorflow 2.0:如何像使用PyTorch一样完全自定义Tensorflow训练循环?、TensorFlow Hub介绍:TensorFlow中可重用的机器学习模块库的实用方法。
本文目录一览:- TensorFlow中卷积的自定义填充(tensorflow卷积操作)
- Effective TensorFlow Chapter 4: TensorFlow中的广播Broadcast机制【转】
- python-在Tensorflow中将自定义渐变定义为类方法
- Tensorflow 2.0:如何像使用PyTorch一样完全自定义Tensorflow训练循环?
- TensorFlow Hub介绍:TensorFlow中可重用的机器学习模块库
TensorFlow中卷积的自定义填充(tensorflow卷积操作)
在tensorflow函数tf.nn.conv2d中,padding选项仅具有’SAME’和’VALID’。
但是在Caffe的转换层中,有pad选项可以定义要(隐式)添加到输入每一侧的像素数。
如何在Tensorflow中实现这一目标?
非常感谢你。
答案1
小编典典您可以在应用前使用tf.pad()
(请参阅doc)对Tensor进行tf.nn.conv2d(...,padding="VALID")
填充(有效的填充表示无填充)。
例如,如果要填充高2像素,宽1像素的图像,然后应用5x5内核进行卷积:
input = tf.placeholder(tf.float32, [None, 28, 28, 3])padded_input = tf.pad(input, [[0, 0], [2, 2], [1, 1], [0, 0]], "CONSTANT")filter = tf.placeholder(tf.float32, [5, 5, 3, 16])output = tf.nn.conv2d(padded_input, filter, strides=[1, 1, 1, 1], padding="VALID")
output
将具有shape [None, 28, 26, 16]
,因为您的填充只有1个宽度。
Effective TensorFlow Chapter 4: TensorFlow中的广播Broadcast机制【转】
本文转载自:https://blog.csdn.net/LoseInVain/article/details/78763303
TensorFlow支持广播机制(Broadcast),可以广播元素间操作(elementwise operations)。正常情况下,当你想要进行一些操作如加法,乘法时,你需要确保操作数的形状是相匹配的,如:你不能将一个具有形状[3, 2]的张量和一个具有[3,4]形状的张量相加。但是,这里有一个特殊情况,那就是当你的其中一个操作数是一个具有单独维度(singular dimension)的张量的时候,TF会隐式地在它的单独维度方向填满(tile),以确保和另一个操作数的形状相匹配。所以,对一个[3,2]的张量和一个[3,1]的张量相加在TF中是合法的。(译者:这个机制继承自numpy的广播功能。其中所谓的单独维度就是一个维度为1,或者那个维度缺失,具体可参考numpy broadcast)。
import tensorflow as tf
a = tf.constant([[1., 2.], [3., 4.]]) b = tf.constant([[1.], [2.]]) # c = a + tf.tile(b, [1, 2]) c = a + b
- 1
- 2
- 3
- 4
- 5
- 6
广播机制允许我们在隐式情况下进行填充(tile),而这可以使得我们的代码更加简洁,并且更有效率地利用内存,因为我们不需要另外储存填充操作的结果。一个可以表现这个优势的应用场景就是在结合具有不同长度的特征向量的时候。为了拼接具有不同长度的特征向量,我们一般都先填充输入向量,拼接这个结果然后进行之后的一系列非线性操作等。这是一大类神经网络架构的共同套路(common pattern)
a = tf.random_uniform([5, 3, 5])
b = tf.random_uniform([5, 1, 6]) # concat a and b and apply nonlinearity tiled_b = tf.tile(b, [1, 3, 1]) c = tf.concat([a, tiled_b], 2) d = tf.layers.dense(c, 10, activation=tf.nn.relu)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
但是这个可以通过广播机制更有效地完成。我们利用事实f(m(x+y))=f(mx+my)f(m(x+y))=f(mx+my),简化我们的填充操作。因此,我们可以分离地进行这个线性操作,利用广播机制隐式地完成拼接操作。
pa = tf.layers.dense(a, 10, activation=None)
pb = tf.layers.dense(b, 10, activation=None)
d = tf.nn.relu(pa + pb)
- 1
- 2
- 3
事实上,这个代码足够通用,并且可以在具有抽象形状(arbitrary shape)的张量间应用:
def merge(a, b, units, activation=tf.nn.relu):
pa = tf.layers.dense(a, units, activation=None) pb = tf.layers.dense(b, units, activation=None) c = pa + pb if activation is not None: c = activation(c) return c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
一个更为通用函数形式如上所述:
目前为止,我们讨论了广播机制的优点,但是同样的广播机制也有其缺点,隐式假设几乎总是使得调试变得更加困难,考虑下面的例子:
a = tf.constant([[1.], [2.]])
b = tf.constant([1., 2.])
c = tf.reduce_sum(a + b)
- 1
- 2
- 3
你猜这个结果是多少?如果你说是6,那么你就错了,答案应该是12.这是因为当两个张量的阶数不匹配的时候,在进行元素间操作之前,TF将会自动地在更低阶数的张量的第一个维度开始扩展,所以这个加法的结果将会变为[[2, 3], [3, 4]],所以这个reduce的结果是12.
(译者:答案详解如下,第一个张量的shape为[2, 1],第二个张量的shape为[2,]。因为从较低阶数张量的第一个维度开始扩展,所以应该将第二个张量扩展为shape=[2,2],也就是值为[[1,2], [1,2]]。第一个张量将会变成shape=[2,2],其值为[[1, 1], [2, 2]]。)
解决这种麻烦的方法就是尽可能地显示使用。我们在需要reduce某些张量的时候,显式地指定维度,然后寻找这个bug就会变得简单:
a = tf.constant([[1.], [2.]])
b = tf.constant([1., 2.])
c = tf.reduce_sum(a + b, 0)
- 1
- 2
- 3
这样,c的值就是[5, 7],我们就容易猜到其出错的原因。一个更通用的法则就是总是在reduce操作和在使用tf.squeeze
中指定维度。
python-在Tensorflow中将自定义渐变定义为类方法
我需要将方法定义为自定义渐变,如下所示:
class CustGradClass:
def __init__(self):
pass
@tf.custom_gradient
def f(self,x):
fx = x
def grad(dy):
return dy * 1
return fx,grad
我收到以下错误:
ValueError: Attempt to convert a value (<main.CustGradClass object at 0x12ed91710>) with an unsupported type () to a Tensor.
原因是自定义渐变接受函数f(* x),其中x是张量序列.传递的第一个参数是对象本身,即自我.
从documentation开始:
f: function f(*x) that returns a tuple (y,grad_fn) where:
x is a sequence of Tensor inputs to the function.
y is a Tensor or sequence of Tensor outputs of applying TensorFlow operations in f to x.
grad_fn is a function with the signature g(*grad_ys)
我该如何运作?我需要继承一些python tensorflow类吗?
我正在使用TF版本1.12.0和渴望模式.
import tensorflow as tf
class CustGradClass:
def __init__(self):
self.f = tf.custom_gradient(lambda x: CustGradClass._f(self,x))
@staticmethod
def _f(self,x):
fx = x * 1
def grad(dy):
return dy * 1
return fx,grad
with tf.Graph().as_default(),tf.Session() as sess:
x = tf.constant(1.0)
c = CustGradClass()
y = c.f(x)
print(tf.gradients(y,x))
# [<tf.Tensor 'gradients/IdentityN_grad/mul:0' shape=() dtype=float32>]
编辑:
如果您想在不同的类上多次执行此操作,或者只想使用更可重用的解决方案,则可以使用如下所示的装饰器:
import functools
import tensorflow as tf
def tf_custom_gradient_method(f):
@functools.wraps(f)
def wrapped(self,*args,**kwargs):
if not hasattr(self,'_tf_custom_gradient_wrappers'):
self._tf_custom_gradient_wrappers = {}
if f not in self._tf_custom_gradient_wrappers:
self._tf_custom_gradient_wrappers[f] = tf.custom_gradient(lambda *a,**kw: f(self,*a,**kw))
return self._tf_custom_gradient_wrappers[f](*args,**kwargs)
return wrapped
然后,您可以这样做:
class CustGradClass:
def __init__(self):
pass
@tf_custom_gradient_method
def f(self,grad
@tf_custom_gradient_method
def f2(self,x):
fx = x * 2
def grad(dy):
return dy * 2
return fx,grad
Tensorflow 2.0:如何像使用PyTorch一样完全自定义Tensorflow训练循环?
这几乎是我可以做的习惯和裸露的骨头。我还使用了子类化的图层。
import tensorflow as tf
import tensorflow_datasets as tfds
ds = tfds.load('iris',split='train',as_supervised=True)
train = ds.take(125).shuffle(125).batch(1)
test = ds.skip(125).take(25).shuffle(25).batch(1)
class Dense(tf.Module):
def __init__(self,in_features,out_features,activation,name=None):
super().__init__(name=name)
self.activation = activation
self.w = tf.Variable(
tf.initializers.GlorotUniform()([in_features,out_features]),name='weights')
self.b = tf.Variable(tf.zeros([out_features]),name='biases')
def __call__(self,x):
y = tf.matmul(x,self.w) + self.b
return self.activation(y)
class SequentialModel(tf.Module):
def __init__(self,name):
super().__init__(name=name)
self.dense1 = Dense(in_features=4,out_features=16,activation=tf.nn.relu)
self.dense2 = Dense(in_features=16,out_features=32,activation=tf.nn.relu)
self.dense3 = Dense(in_features=32,out_features=3,activation=tf.nn.softmax)
def __call__(self,x):
x = self.dense1(x)
x = self.dense2(x)
x = self.dense3(x)
return x
model = SequentialModel(name='sequential_model')
loss_object = tf.losses.SparseCategoricalCrossentropy(from_logits=False)
def compute_loss(model,x,y):
out = model(x)
loss = loss_object(y_true=y,y_pred=out)
return loss,out
def get_grad(model,y):
with tf.GradientTape() as tape:
loss,out = compute_loss(model,y)
gradients = tape.gradient(loss,model.trainable_variables)
return loss,gradients,out
optimizer = tf.optimizers.Adam()
verbose = "Epoch {:2d} Loss: {:.3f} TLoss: {:.3f} Acc: {:=7.2%} TAcc: {:=7.2%}"
for epoch in range(1,10 + 1):
train_loss = tf.constant(0.)
train_acc = tf.constant(0.)
test_loss = tf.constant(0.)
test_acc = tf.constant(0.)
for n_train,(x,y) in enumerate(train,1):
loss_value,grads,out = get_grad(model,y)
optimizer.apply_gradients(zip(grads,model.trainable_variables))
train_loss += loss_value
train_acc += tf.metrics.sparse_categorical_accuracy(y,out)[0]
for n_test,y) in enumerate(test,_,y)
test_loss += loss_value
test_acc += tf.metrics.sparse_categorical_accuracy(y,out)[0]
print(verbose.format(epoch,tf.divide(train_loss,n_train),tf.divide(test_loss,n_test),tf.divide(train_acc,tf.divide(test_acc,n_test)))
,
虽然我认为张量流错误非常有帮助,但是您的回答是是,您可以从基本到高级使用张量流进行思考。您可以动态或静态地运行网络。
当我想学习张量流和keras时,我在colab上编写了一些代码,您可以找到其中一个与您的问题here相关的代码。但是我会在这里写下您想要的部分(不是完整的代码):
batch_size = 32
epochs = 10
loss_func = keras.losses.CategoricalCrossentropy()
opt = keras.optimizers.Adam(learning_rate=0.003)
(valX,valy) = (trainX[-10000:],trainy[-10000:])
# for easily shuffling later
train_dataset = tf.data.Dataset.from_tensor_slices((trainX,trainy))
# layers
conv1 = Conv2D_custom(32,(3,3),activation='relu',input_shape = trainX.shape[1:])
conv2 = Conv2D_custom(64,activation='relu')
dense = Dense_custom(10,activation='softmax')
max1 = MaxPooling2D((2,2))
max2 = MaxPooling2D((2,2))
flat = Flatten()
dropout = Dropout(0.5)
for i in range(epochs):
print("Epoch: ",i)
epoch_loss = 0
train_dataset = train_dataset.shuffle(buffer_size=1024)
train_batched = train_dataset.batch(batch_size)
for step,(batchX,batchy) in enumerate(train_batched):
with tf.GradientTape() as tape:
x = conv1(batchX)
x = max1(x)
x = conv2(x)
x = max2(x)
x = flat(x)
x = dropout(x,training=True)
x = dense(x)
loss = loss_func(batchy,x)
trainable_vars = conv1.trainable_weights + conv2.trainable_weights + dense.trainable_weights
grads = tape.gradient(loss,trainable_vars)
opt.apply_gradients(zip(grads,trainable_vars))
epoch_loss += loss
if step % 200 == 0:
print("\tStep ",step,":\t loss = ",epoch_loss.numpy()/(step+1))
# epoch ended,validate it
x = conv1(valX)
x = max1(x)
x = conv2(x)
x = max2(x)
x = flat(x)
x = dropout(x,training=False)
x = dense(x)
val_loss = loss_func(valy,x)
print("Epoch ",i," ended.\t","loss = ",epoch_loss.numpy()/len(train_batched),",\tval_loss = ",val_loss.numpy())
它并不漂亮,您可以做得更好(我对tensorflow和keras不太了解)。但是它对于MNIST数据集效果很好,并且可以根据需要进行自定义。
Tensorflow有一个名为Eager execution
的东西,您可以使用它动态运行网络,只需启用它即可。在大多数情况下,tensorflow都与急切的执行本身纠缠不清,甚至您也无需告诉tensorflow何时在eager模式下运行以及何时在图模式下运行(可能时会自动使用图模式以获取更高的性能)。 / p>
再一次,您可以确定可以在所需的每个级别中处理张量流,几乎像在keras中一样,从零开始到高级。
希望它会有所帮助,并为您带来有趣的编程:)
,Tensorflow使用渴望执行,这意味着您的图形是动态连接的。当然,它不像PyTorch那样动态。但是,谷歌正在尽力而为,并在2.0及更高版本中加入了许多功能。
要在Tensorflow中编写自定义循环,您需要使用 tf.GradientTape 。我会说它涉及与pytorch中相同的步骤。计算渐变,然后使用优化程序进行更新。
TensorFlow Hub介绍:TensorFlow中可重用的机器学习模块库
摘要: 本文对TensorFlow Hub库的介绍,并举例说明其用法。
在软件开发中,最常见的失误就是容易忽视共享代码库,而库则能够使软件开发具有更高的效率。从某种意义上来说,它改变了编程的过程。我们常常使用库构建块或模块,并将其连接在一起进行编程。
开发人员是如果使用库的呢?除了共享代码之外,我们还可以共享预训练模型。共享预训练模型能够使开发人员有针对性的开发该模型,而不需要访问计算资源或手头上用于训练模型的原始数据。例如,NASNet架构在GPU上花费数千个小时进行训练。通过共享学习到的权重,其他开发人员就能够更容易重用库和构建模型或架构。
机器学习模型内部的“组成部分”,可以使用TensorFlow Hub进行打包和共享。从某种意义上来讲,除了架构本身,共享预先训练好的模型的同时,也共享了开发模型的计算时间和数据集。
为机器学习开发者提供库产生了TensorFlow Hub库。TensorFlow Hub库是一个在TensorFlow中进行发布和重用中机器学习模块的平台。我们可以在其他类似的任务中重复使用一个模块(一个TensorFlow的独立片段及其权重)。 开发人员也可以重用一个模块使用一个更小的数据集来训练模型,来提高泛化或加快训练速度。下面来看几个具体的例子。
图像再训练
首先,我们从少量的训练数据开始——图像分类器。现代图像识别模型具有数百万个参数,如果从头开始训练,就需要大量的标记数据和计算能力。使用图像再训练技术,就可以使用很少的数据来训练模型,并且计算时间也少得多。以下是TensorFlow Hub的外观。
其基本思想是,用一个现成的图像识别模块从图像中提取特征训练一个新的分类器。正如你所看到的一样,TensorFlow Hub模块可以在构建TensorFlow图时通过URL(或文件路径)进行实例化。TensorFlow Hub上有多种模块可供选择,包括NASNet、MobileNet(包括其最近的V2)、Inception、ResNet等。想要使用某一模块,首先导入TensorFlow Hub,然后将模块的URL地址复制/粘贴到代码中即可。
每个模块都有一个已定义的接口,在不了解其内在结构的情况下,也能够替换使用。这个模块提供了一个检索预期图像大小的方法:只需提供一组有正确形状的图像,然后调用该模块来检索图像的特征表示。该模块负责对图像进行预处理,可以直接将图像转换为其特征表示,然后再构建一个线性模型或其他类型的分类器。
请注意,我们使用的模块是由Google开发的,并且是版本化的(因此模块在实验中不会改变)。和普通Python函数一样,我们也可以使用该模块来构建模型的一部分。一旦导出到磁盘,模块是独立的,无需访问创建和训练该模块的代码和数据(也可以发布代码和数据),也能供其他人所使用。
文本分类
现在你想训练一个模型:将电影评论分为正面或负面,但是只有少量的训练数据(比如只有几百个正面和负面的电影评论)。由于训练数据有限,因此你打算使用以前在大得多的语料库上训练过的词嵌入数据集。以下是使用TensorFlow Hub思路。
同样,首先选择一个模块。TensorFlow Hub提供了多种文本模块,包括基于各种语言(EN,JP,DE和ES)的神经网络语言模型,在维基百科上训练的Word2vec模型和在Google新闻上训练的NNLM嵌入。
在这里,我们使用一个模块来进行文本嵌入。使用上面的代码下载一个模块,用来对一个句子进行预处理,然后检索每个块的嵌入,这就意味着可以直接将数据集中的句子转换为适合分类器的格式。该模块负责标记句子和其他逻辑(如处理词典外的单词)。预处理逻辑和嵌入都封装在一个模块中,使在各种不同的数据集上的文字嵌入和预处理策略变得更加容易,而不必对代码进行大幅度的变动。
通用句子编码器
我们还分享了一个新的TensorFlow Hub模块!下面是通用句子编码器。它是在各种各样的数据集(“通用”)上训练的句级嵌入模块。其功能是语义相似性、自定义文本分类和聚类。
这篇文章展示了如何在任何一个可嵌入句子的TF-Hub模块上训练一个简单的二进制文本分类器。
如在图像再训练中,使用相对较少的标记数据使模块适应某一任务,如餐厅评论。查看本教程以了解更多信息。
其他模块
TensorFlow Hub不仅仅是图像和文本分类。用于Progressive GAN和Google地标深层特征的其他模块请查看链接。
注意事项
使用TensorFlow Hub模块时需要考虑几个重要因素:首先,请记住模块包含的可运行的代码,一定要使用可信来源的模块;其次,正如所有的机器学习一样,公平性是一个很重要的因素。
上面的两个例子都使用了预先训练好的大数据集。当重复使用这样的数据集时,注意其包含的数据是否存在偏差,以及这些是如何影响正在构建的模型和用户的。
本文由阿里云云栖社区组织翻译。
文章原标题《Introducing TensorFlow Hub: A Library for Reusable Machine Learning Modules in TensorFlow》,译者:Mags,审校:袁虎。
文章为简译,更为详细的内容,请查看原文。
今天关于TensorFlow中卷积的自定义填充和tensorflow卷积操作的讲解已经结束,谢谢您的阅读,如果想了解更多关于Effective TensorFlow Chapter 4: TensorFlow中的广播Broadcast机制【转】、python-在Tensorflow中将自定义渐变定义为类方法、Tensorflow 2.0:如何像使用PyTorch一样完全自定义Tensorflow训练循环?、TensorFlow Hub介绍:TensorFlow中可重用的机器学习模块库的相关知识,请在本站搜索。
本文标签: