【keras】keras使用方法集合(持续更新中)

本文内容如下:

1. keras中,shape如何定义?

2. 关于model.compile 的参数传递,传递字符串呢?还是传递对象?

3. 如何获取模型中的每个layer信息?如input_shape,output_shape,layer的参数配置等

4. 如何将预训练好的词向量加载到Embedding layer中?

5. 如何获取单个layer的weight?

6. keras如何与tensorboard结合?

7. keras 如何做fine-tuning?

8. keras使用过程中,如何构造data与label?(将其构造为numpy数组即可)

9. 如果data过大,不适合一次性加载到内存中,该如何处理?(文本训练一般用不到,毕竟txt文件,1M就是100万char,已经很大了。一本小说几百万字,也就几M,十几M)

10 . keras中Sequential 模型 与函数式API的区别是什么?

11.  GRU与LSTM的参数如何理解?

【一】keras中的shape定义

keras中,Sequential 模型中的第一层需要指定shape,否则keras无法自动计算后面的layer的shape而运行报错。

1. 通过参数 input_shape 指定shape,该参数的shape信息不包含batch_size信息,batch_size默认为None

例如:指定shape为2D,则  input_shape = (100,)或者  input_shape = (None,)

          指定shape为3D,则 input_shape = (100,20) 或者 input_shape = (None,20)

         input_shape 可以是元组,也可以是列表。还是统一用元组吧。

2. 通过参数 batch_input_shape指定shape,该参数的shape信息包含batch_size,且第一个维度就是batch_size大小。

例如:指定shape为2D,则  batch_input_shape = (None,100,)或者  batch_input_shape = (None,None)

          指定shape为3D,则 batch_input_shape = (None,100,20) 或者 batch_input_shape = (None,None,20)

代码示例如下:

# -*- coding:utf-8 -*-
import keras
from keras.layers import Dense

model = keras.Sequential()
# shape一般使用元组定义,列表也行,还是统一使用元组表示吧
# 必须是input_shape=(2,)不能是input_shape=(2)
# 输入是2D,shape = (None,2)
model.add(Dense(units=3,input_shape=(2,)))
# shape = (None, 2, 3)
#model.add(Dense(units=3,input_shape=(2,2)))
#model.add(Dense(units=3,input_shape=[2,2]))
# shape=(2,3)
#model.add(Dense(units=3,batch_input_shape=(2,3)))
model.summary()

3. 那是不是第一层的layer都需要通过input_shape或者batch_input_shape参数来指定shape信息呢?

答案是否定的,只要能推算出shape即可具体可以参见:https://keras.io/zh/getting-started/sequential-model-guide/

这里对常见的第一层layer做个举例。

3.1 第一层为Embedding

情况一:不知道输入数据的长度,只知道词典的大小与embedding_size。

model = keras.Sequential()
# input_dim就是词典大小,out_dim就是embedding_size
model.add(Embedding(input_dim=10000,output_dim=100))
model.summary()

结果为:
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, None, 100)         1000000   
=================================================================

情况二:知道数据数据的长度,比如:输入定长的句子

model = keras.Sequential()
# input_length就是数据数据的长度
model.add(Embedding(input_dim=10000,output_dim=100,input_length=200))
model.summary()

结果为:
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 200, 100)          1000000   
=================================================================

embedding layer作为第一层时,就默认了,输入数据必须是2D,经过embedding layer后,输出一定为3D。

【二】model.compile 的参数传递

1. 参数之优化器,均在 keras.optimizers 模块下面定义

model.compile(optimizer='Adam')
model.compile(optimizer=keras.optimizers.Adam(lr=0.01))

2. 参数之损失 loss,均在 keras.losses下定义

该loss可以使用keras.losses模块下面定义的loss,也可以使用tf.loss模块下面定义的loss,可以参考:https://keras.io/zh/losses/

model.compile(optimizer=keras.optimizers.Adam(),loss=tf.losses.sigmoid_cross_entropy)
model.compile(optimizer='Adam',loss=keras.losses.binary_crossentropy)

3. 参数之 metrics

在训练和测试期间的模型评估标准。通常你会使用 metrics = ['accuracy']。

metrics可以支持中评估方法:分别是:'accuracy', 'acc', 'crossentropy', 'ce'

这个从源码可以看出,虽然传递的是字符串,但是最终还是使用 keras.metrics.模块中的评估方法,而且从字符串到方法的映射,还和loss函数有关系。

从源码来看,传递'acc'和‘accuracy’是一样的,传递'ce‘和'crossentropy‘是一样的。一个是简写,一个是全称罢了。

其他参数暂时不探讨了,可以参考源码或者keras官方文档(https://keras.io/zh/models/sequential/)

【三】如何获取模型中的每个layer信息?

# -*- coding:utf-8 -*-
import keras
import tensorflow as tf
from keras.layers import Dense
from keras.layers import Embedding
model = keras.Sequential()
model.add(Embedding(input_dim=10000,output_dim=100,input_length=200,name="emb"))
model.summary()
# 通过layer的名字获取layer
emb_layer = model.get_layer(name="emb")
# 获取layer的shape信息
print(emb_layer.input_shape)
print(emb_layer.output_shape)
# 获取layer的参数配置信息
print(emb_layer.get_config())



结果如下:
(None, 200)
(None, 200, 100)
{'name': 'emb', 'trainable': True, 'batch_input_shape': (None, 200), 'dtype': 'float32', 'input_dim': 10000, 'output_dim': 100, 'embeddings_initializer': {'class_name': 'RandomUniform', 'config': {'minval': -0.05, 'maxval': 0.05, 'seed': None}}, 'embeddings_regularizer': None, 'activity_regularizer': None, 'embeddings_constraint': None, 'mask_zero': False, 'input_length': 200}

【四】如何将预训练好的词向量加载到Embedding layer中?

这里以斯坦福大学通过glove训练好的word embedding为例(https://nlp.stanford.edu/projects/glove/)

# 初始化词典
embedding_matrix = np.zeros(shape=(V,m))
word_index = {}
embedding_index = {}
# 选择m=50的预训练数据,将预训练的词与vector提取到embedding_index中存储起来
with open("glove.6B.50d.txt") as f:
    for line in f:
        values = line.split()
        word = values[0]
        coefs = np.asarray(values[1:],dtype=np.float32)
        embedding_index[word] = coefs
'''
x_train,t_train = imdb_load("train")
token = text.Tokenizer(num_words=max_features)
token.fit_on_texts(x_train)
'''
# 获取当前语料(imdb)的词
word_index = token.word_index
not_find = 0
for word,i in word_index.items():
    if i < V:
        # 查预训练的词表
        embedding_vec = embedding_index.get(word)
        if embedding_vec is not None:
            embedding_matrix[i] = embedding_vec
        else:
            not_find += 1
# 将权值设置到embedding layer中
model.layers[0].set_weigth([embedding_matrix])
# frozen embedding layer,也可以不冻结。不冻结的话就可以fine-tuning该层
model.layers[0].trainable = False

【五】 如何获取单个layer的weight?

# 通过layer的名字获取layer
emb_layer = model.get_layer(name="emb")
weigth = emb_layer.get_weights()
print(weigth)

返回的是np数组
结果如下:
[array([[-0.04013518,  0.04399543,  0.03000858, ..., -0.0194814 ,
        -0.04092554, -0.02486232],
       [-0.00160228, -0.04412872,  0.03846688, ...,  0.02017101,
        -0.02005241,  0.01420185],
       [ 0.04151604,  0.04445838,  0.03028882, ...,  0.04380548,
         0.04354296, -0.02567321],
       ...,
       [ 0.02195187, -0.01256204,  0.01097646, ..., -0.04138255,
        -0.01372109,  0.02588195],
       [-0.00363313,  0.01956742, -0.00567082, ..., -0.03723276,
         0.02284933, -0.04223878],
       [-0.0346414 ,  0.01633375,  0.03251269, ...,  0.04532002,
        -0.02762125, -0.03938962]], dtype=float32)]

【六】keras如何与tensorboard结合?

使用方式比较简单,给fit函数传递一个keras.callbacks.TensorBoard 作为callback对象即可

    tensorboard = keras.callbacks.TensorBoard(log_dir="./logs/")
    train_history = model.fit(x=x_train,
                              y=y_train,
                              batch_size=128,
                              epochs=1,
                              validation_data=(x_test,y_test),
                              callbacks=[tensorboard])

启动tensorboard(tensorboard --logdir=./logs/)之后,然后在浏览器输入:http://localhost:6006 ,即可看到各种信息

参考官方文档(https://keras.io/zh/callbacks/),该回调接口,有很多参数。

其中关于embedding的可视化,参考官方案例:(https://github.com/keras-team/keras/blob/master/examples/tensorboard_embeddings_mnist.py)

【七】keras 如何做fine-tuning?

1. fine-tuning 一般是指,将模型的部分层保留,部分层删除或者修改,进而形成一个新的模型。比如在CV的分类网络中,一本将基于ImageNet训练出来的resnet等网络的最后一层修改,然后将预训练的模型参数导入新的模型中。那么要实现fine-tuning,在keras中如何实现呢?

思路还是一致:先保存原有模型参数,构造新模型,最后将原有模型中与新模型layer一致的参数,用过layer-name导入到新的模型中。

1)定义原始模型,并保存模型参数。

# -*- coding:utf-8 -*-
import keras
from keras.layers import Dense
model = keras.Sequential()
model.add(Dense(units=5,batch_input_shape=(2,5),name="fc1"))
model.add(Dense(units=3,name="fc2"))
model.summary()
# 保存模型
model.save_weights('./models/fc.h5')

2)定义新模型,加载原始模型的权值参数

# -*- coding:utf-8 -*-
import keras
from keras.layers import Dense

# 定义模型,模型的前2层和原始模型一致
model = keras.Sequential()
model.add(Dense(units=5,batch_input_shape=(2,5),name="fc1"))
model.add(Dense(units=3,name="fc2"))
# 第三层是新模型新增的层
model.add(Dense(units=1,name="fc3"))
# 加载原始模型的参数到新模型中,通过设置by_name=True来实现,即通过layer名字查找对应的参数,其底层机制,与tf和caffe应该是一致的
model.load_weights(filepath='./models/fc.h5',by_name=True)
model.summary()



注意地点,进行参数加载时,layer的配置信息必须完全一致,比如shape

【十】 keras中Sequential 模型 与函数式API的区别是什么?

1. 首先看看官网对函数式API的定义:

2. 函数式API的使用方法这里便不再讲述了,可参考:https://keras.io/zh/getting-started/functional-api-guide/

3. 函数式API的返回值是什么?

  • 网络层的实例是可调用的,它以张量为参数,并且返回一个张量

     ----- 这个是官网描述,我们来看看代码

from keras.layers import Input


x = Input(shape=(5,))
print(type(x))

结果如下:
<class 'tensorflow.python.framework.ops.Tensor'>

可以看出,网络层的实例返回的确是张量。

使用函数式API,可以向TensorFlow一样编写代码,而且比TensorFlow简单很多。

x = Input(shape=(5,),name="x")
fc1 = Dense(units=5)(x)
fc1 = keras.activations.relu(x=fc1)
print(fc1)
# 结果如下
Tensor("Relu:0", shape=(?, 5), dtype=float32)

keras.layer将所需定义的W、b等variable自动定义了。

有些layer可能返回多个输出值,当我们仅需要其中的几个返回值而丢弃其他的返回值值时,函数式API给以满足这种需求(比如GRU/LSTM)

【十一】GRU与LSTM的参数如何理解?

1. GRU参数

2. 这个return相关的两个参数,实在令人费解,GRU和LSTM还不一样。

先看看例子:

from keras.layers import Input
from keras.layers import GRU
from keras.layers import LSTM

x = Input(shape=(None, 20))

y = GRU(units=10)
print(y(x))
Tensor("gru_1/TensorArrayReadV3:0", shape=(?, 10), dtype=float32)

y = GRU(units=10,return_state=True)
print(y(x))
[<tf.Tensor 'gru_2/TensorArrayReadV3:0' shape=(?, 10) dtype=float32>, <tf.Tensor 'gru_2/while/Exit_2:0' shape=(?, 10) dtype=float32>]


y = GRU(units=10,return_state=True,return_sequences=True)
print(y(x))
[<tf.Tensor 'gru_3/transpose_1:0' shape=(?, ?, 10) dtype=float32>, <tf.Tensor 'gru_3/while/Exit_2:0' shape=(?, 10) dtype=float32>]


y = LSTM(units=10)
print(y(x))
Tensor("lstm_1/TensorArrayReadV3:0", shape=(?, 10), dtype=float32)

y = LSTM(units=10,return_state=True)
print(y(x))
[<tf.Tensor 'lstm_2/TensorArrayReadV3:0' shape=(?, 10) dtype=float32>, <tf.Tensor 'lstm_2/while/Exit_2:0' shape=(?, 10) dtype=float32>, <tf.Tensor 'lstm_2/while/Exit_3:0' shape=(?, 10) dtype=float32>]


y = LSTM(units=10,return_state=True,return_sequences=True)
print(y(x))
[<tf.Tensor 'lstm_3/transpose_1:0' shape=(?, ?, 10) dtype=float32>, <tf.Tensor 'lstm_3/while/Exit_2:0' shape=(?, 10) dtype=float32>, <tf.Tensor 'lstm_3/while/Exit_3:0' shape=(?, 10) dtype=float32>]

return_state: 布尔值。除了输出之外是否返回最后一个状态 ----> 也就是返回值中的list中的第二个值,list[1]。即LSTM或者GRU计算完成之后的左右一个状态值

return_sequences: 布尔值。是返回输出序列中的最后一个输出,还是全部序列 ------>也就是返回值list中的第一个值,list[0]。即LSTM或者GRU,是否返回所有的输出值,即y0,y1,y2,......,yt。如果返回,则增加一个shape维度。

x = Input(shape=(50, 20))
y = GRU(units=10)
print(y(x))
y = GRU(units=10,return_sequences=True)
print(y(x))

Tensor("gru_1/TensorArrayReadV3:0", shape=(?, 10), dtype=float32)
Tensor("gru_2/transpose_1:0", shape=(?, ?, 10), dtype=float32)

关于这return的配置使用,keras给出了一个官方案例,在实现seq2seq时提到了。(https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq.py)

猜你喜欢

转载自my.oschina.net/u/3800567/blog/2965731