keras embeding设置初始值的两种方式
随机初始化Embedding
from keras.models import Sequential
from keras.layers import Embedding
import numpy as np
model = Sequential()
model.add(Embedding(1000, 64, input_length=10))
# the model will take as input an integer matrix of size (batch, input_length).
# the largest integer (i.e. word index) in the input should be no larger than 999 (vocabulary size).
# now model.output_shape == (None, 10, 64), where None is the batch dimension.
input_array = np.random.randint(1000, size=(32, 10))
model.compile('rmsprop', 'mse')
output_array = model.predict(input_array)
print(output_array)
assert output_array.shape == (32, 10, 64)
使用weights参数指明embedding初始值
import numpy as np
import keras
m = keras.models.Sequential()
"""
可以通过weights参数指定初始的weights参数
因为Embedding层是不可导的
梯度东流至此回,所以把embedding放在中间层是没有意义的,emebedding只能作为第一层
注意weights到embeddings的绑定过程很复杂,weights是一个列表
"""
embedding = keras.layers.Embedding(input_dim=3, output_dim=2, input_length=1, weights=[np.arange(3 * 2).reshape((3, 2))], mask_zero=True)
m.add(embedding) # 一旦add,就会自动调用embedding的build函数,
print(keras.backend.get_value(embedding.embeddings))
m.compile(keras.optimizers.RMSprop(), keras.losses.mse)
print(m.predict([1, 2, 2, 1, 2, 0]))
print(m.get_layer(index=0).get_weights())
print(keras.backend.get_value(embedding.embeddings))
给embedding设置初始值的第二种方式:使用initializer
import numpy as np
import keras
m = keras.models.Sequential()
"""
可以通过weights参数指定初始的weights参数
因为Embedding层是不可导的
梯度东流至此回,所以把embedding放在中间层是没有意义的,emebedding只能作为第一层
给embedding设置权值的第二种方式,使用constant_initializer
"""
embedding = keras.layers.Embedding(input_dim=3, output_dim=2, input_length=1, embeddings_initializer=keras.initializers.constant(np.arange(3 * 2, dtype=np.float32).reshape((3, 2))))
m.add(embedding)
print(keras.backend.get_value(embedding.embeddings))
m.compile(keras.optimizers.RMSprop(), keras.losses.mse)
print(m.predict([1, 2, 2, 1, 2]))
print(m.get_layer(index=0).get_weights())
print(keras.backend.get_value(embedding.embeddings))
关键的难点在于理清weights是怎么传入到embedding.embeddings张量里面去的。
Embedding是一个层,继承自Layer,Layer有weights参数,weights参数是一个list,里面的元素都是numpy数组。在调用Layer的构造函数的时候,weights参数就被存储到了_initial_weights变量
basic_layer.py 之Layer类
if 'weights' in kwargs:
self._initial_weights = kwargs['weights']
else:
self._initial_weights = None
当把Embedding层添加到模型中、跟模型的上一层进行拼接的时候,会调用layer(上一层)函数,此处layer是Embedding实例,Embedding是一个继承了Layer的类,Embedding类没有重写__call__()方法,Layer实现了__call__()方法。父类Layer的__call__方法调用子类的call()方法来获取结果。所以最终调用的是Layer.__call__()。在这个方法中,会自动检测该层是否build过(根据self.built布尔变量)。
Layer.__call__函数非常重要。
def __call__(self, inputs, **kwargs):
"""Wrapper around self.call(), for handling internal references.
If a Keras tensor is passed:
- We call self._add_inbound_node().
- If necessary, we `build` the layer to match
the _keras_shape of the input(s).
- We update the _keras_shape of every input tensor with
its new shape (obtained via self.compute_output_shape).
This is done as part of _add_inbound_node().
- We update the _keras_history of the output tensor(s)
with the current layer.
This is done as part of _add_inbound_node().
# Arguments
inputs: Can be a tensor or list/tuple of tensors.
**kwargs: Additional keyword arguments to be passed to `call()`.
# Returns
Output of the layer's `call` method.
# Raises
ValueError: in case the layer is missing shape information
for its `build` call.
"""
if isinstance(inputs, list):
inputs = inputs[:]
with K.name_scope(self.name):
# Handle laying building (weight creating, input spec locking).
if not self.built:#如果未曾build,那就要先执行build再调用call函数
# Raise exceptions in case the input is not compatible
# with the input_spec specified in the layer constructor.
self.assert_input_compatibility(inputs)
# Collect input shapes to build layer.
input_shapes = []
for x_elem in to_list(inputs):
if hasattr(x_elem, '_keras_shape'):
input_shapes.append(x_elem._keras_shape)
elif hasattr(K, 'int_shape'):
input_shapes.append(K.int_shape(x_elem))
else:
raise ValueError('You tried to call layer "' +
self.name +
'". This layer has no information'
' about its expected input shape, '
'and thus cannot be built. '
'You can build it manually via: '
'`layer.build(batch_input_shape)`')
self.build(unpack_singleton(input_shapes))
self.built = True#这句话其实有些多余,因为self.build函数已经把built置为True了
# Load weights that were specified at layer instantiation.
if self._initial_weights is not None:#如果传入了weights,把weights参数赋值到每个变量,此处会覆盖上面的self.build函数中的赋值。
self.set_weights(self._initial_weights)
# Raise exceptions in case the input is not compatible
# with the input_spec set at build time.
self.assert_input_compatibility(inputs)
# Handle mask propagation.
previous_mask = _collect_previous_mask(inputs)
user_kwargs = copy.copy(kwargs)
if not is_all_none(previous_mask):
# The previous layer generated a mask.
if has_arg(self.call, 'mask'):
if 'mask' not in kwargs:
# If mask is explicitly passed to __call__,
# we should override the default mask.
kwargs['mask'] = previous_mask
# Handle automatic shape inference (only useful for Theano).
input_shape = _collect_input_shape(inputs)
# Actually call the layer,
# collecting output(s), mask(s), and shape(s).
output = self.call(inputs, **kwargs)
output_mask = self.compute_mask(inputs, previous_mask)
# If the layer returns tensors from its inputs, unmodified,
# we copy them to avoid loss of tensor metadata.
output_ls = to_list(output)
inputs_ls = to_list(inputs)
output_ls_copy = []
for x in output_ls:
if x in inputs_ls:
x = K.identity(x)
output_ls_copy.append(x)
output = unpack_singleton(output_ls_copy)
# Inferring the output shape is only relevant for Theano.
if all([s is not None
for s in to_list(input_shape)]):
output_shape = self.compute_output_shape(input_shape)
else:
if isinstance(input_shape, list):
output_shape = [None for _ in input_shape]
else:
output_shape = None
if (not isinstance(output_mask, (list, tuple)) and
len(output_ls) > 1):
# Augment the mask to match the length of the output.
output_mask = [output_mask] * len(output_ls)
# Add an inbound node to the layer, so that it keeps track
# of the call and of all new variables created during the call.
# This also updates the layer history of the output tensor(s).
# If the input tensor(s) had not previous Keras history,
# this does nothing.
self._add_inbound_node(input_tensors=inputs,
output_tensors=output,
input_masks=previous_mask,
output_masks=output_mask,
input_shapes=input_shape,
output_shapes=output_shape,
arguments=user_kwargs)
# Apply activity regularizer if any:
if (hasattr(self, 'activity_regularizer') and
self.activity_regularizer is not None):
with K.name_scope('activity_regularizer'):
regularization_losses = [
self.activity_regularizer(x)
for x in to_list(output)]
self.add_loss(regularization_losses,
inputs=to_list(inputs))
return output
如果没有build过,会自动调用Embedding类的build()函数。Embedding.build()这个函数并不会去管weights,如果它使用的initializer没有传入,self.embeddings_initializer会变成随机初始化。如果传入了,那么在这一步就能够把weights初始化好。如果同时传入embeddings_initializer和weights参数,那么weights参数稍后会把Embedding#embeddings覆盖掉。
embedding.py Embedding类的build函数
def build(self, input_shape):
self.embeddings = self.add_weight(
shape=(self.input_dim, self.output_dim),
initializer=self.embeddings_initializer,
name='embeddings',
regularizer=self.embeddings_regularizer,
constraint=self.embeddings_constraint,
dtype=self.dtype)
self.built = True
综上,在keras中,使用weights给Layer的变量赋值是一个比较通用的方法,但是不够直观。keras鼓励多多使用明确的initializer,而尽量不要触碰weights。
keras embeding设置初始值的两种方式的更多相关文章
- HTML中设置背景图的两种方式
HTML中设置背景图的两种方式 1.background background:url(images/search.png) no-repeat top; 2.background-image ...
- JavaWeb后台从input表单获取文本值的两种方式
JavaWeb后台从input表单获取文本值的两种方式 #### index.html <!DOCTYPE html> <html lang="en"> & ...
- drupal7 覆写node-type.tpl.php获取字段值的两种方式
字段的机读名称为:field_publication_date <!-- 下面两种方式都可以获取node字段的值--> 出版时间: <?php print date('Y-m-d', ...
- linux 设置开机启动项两种方式
原文链接:http://blog.csdn.net/karchar/article/details/52489572 有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务. 在解问题之前 ...
- VS中设置#define _CRT_SECURE_NO_WARNINGS的两种方式
1.我们在编译老的用C语言的开源项目如lua源包的时候,可能因为一些老的.c文件使用了strcpy,scanf等不安全的函数,而报警告和错误,而导致无法编译通过. 2.此时我们有两种解决方案: a.在 ...
- npm获取配置值的两种方式
命令行标记 在命令行上放置--foo bar设置foo配置参数为bar. 一个 -- 参数(argument)告诉cli解析器停止读取flags.一个 在命令行结尾的--flag参数(paramete ...
- js对象取值的两种方式
:"李四"}; var v1 = obj.name1; //张三, 使用点的方式 //报错,不能使用点的方式 ]; //李四,使用中括号的方式 var key = "na ...
- 如果js设置移动端有两种方式 大家可以参考
//使用em单位 var scaleObj = { documentEle : document.documentElement, deviceWidth : document.documentEle ...
- checkbox设置单选的的两种方式
一.如果 <input name="ck" type="checkbox">是页面加载就有的 $("#input[name=ck]&quo ...
随机推荐
- 在springboot项目中使用mybatis 集成 Sharding-JDBC
前段时间写了篇如何使用Sharding-JDBC进行分库分表的例子,相信能够感受到Sharding-JDBC的强大了,而且使用配置都非常干净.官方支持的功能还包括读写分离.分布式主键.强制路由等.这里 ...
- 使用Java语言开发微信公众平台(三)——被关注回复与关键词回复
在上一篇文章中,我们实现了文本消息的接收与响应.可以在用户发送任何内容的时候,回复一段固定的文字.本章节中,我们将对上一章节的代码进行适当的完善,同时实现[被关注回复与关键词回复]功能. 一.微信可提 ...
- 【Spark】SparkStreaming-提交到集群运行
SparkStreaming-提交到集群运行 spark streaming 提交_百度搜索 SparkStreaming示例在集群中运行 - CSDN博客
- 【python3】集合set (转)
https://www.cnblogs.com/onepeace/p/4791578.html set原理 Python 还 包 含 了 一 个 数 据 类 型—— set ( 集 合 ) . 集 合 ...
- Spring(十二):IOC容器中Bean的生命周期方法
IOC容器中Bean的生命周期方法 1)Spring IOC容器可以管理Bean的声明周期,Spring允许在Bean生命周期的特定点执行定制的任务. 2)Spring IOC容器对Bean的生命周期 ...
- Linux中盘符的两种挂载方法
相信接触过Linux系统的人对于mount命令都不陌生,今天是农历2017年的最后一个工作日,趁着时光还在,就说一下两种不同的挂载方法吧. 课前小知识: 命令格式:mount [-t vfstype] ...
- 怎样编写YARN应用程序
(注意:本文的分析基于Hadoop trunk上的"Revision 1452188"版本号,详细可參考:http://svn.apache.org/repos/asf/hadoo ...
- GPUImage简单滤镜使用(一)
今天来学习一下一个简单滤镜使用的流程,通过调节亮度滤镜来了解.先将GPUImage库导入到项目中,引入头文件"GPUImage.h" 一.创建亮度滤镜对象 GPUImag ...
- nginx服务企业应用
1.1 常用来提供静态服务的软件 Apache :这是中小型Web服务的主流,Web服务器中的老大哥, Nginx :大型网站Web服务的主流,曾经Web服务器中的初生牛犊,现已长大. Nginx 的 ...
- 坑人无数的Redis面试题
https://baijiahao.baidu.com/s?id=1588454565071211950&wfr=spider&for=pc 坑人无数的Redis面试题