zoukankan      html  css  js  c++  java
  • keras

    keras

    keras作为深度学习框架,为用户提供简洁友好的接口,后端可以使用TensorFlow, Theano, CNTK。

    1. 序贯模型

    是线性的,“一条路走到黑”时的网络可以使用序贯模型。

    from keras .models import Sequential
    from keras.layers import Dense,Activation
    model = Sequential([Dense(32,units = 784),Activation('relu'),Dense(10),Activation('softmax'),])

    也可以通过add函数添加网络层:

    model = Sequential()
    model.add(Dense(32, input_shape=(784,)))
    model.add(Activation('relu'))
    • 第一层需要指定输入数据的shape,后续层会自动推导出数据的shape。batch_size参数是不需要给出的,如果是B x H x W x C这样的数据,input_shape=(H, W, C)就好。

    • 使用compile()进行参数配置,compile接收优化器,loss, 以及评估标准, optmizer, loss可以接收字符串或者对象,评估指标需要传入一个列表,metrics=['accuracy']。

    • 最后使用fit()进行模型的训练,最简单的只需传入model.fit(data, label)即可,数据是numpy.ndarray形式,也可以指定其它参数,如epochs=100, batch_size=64, validation_split=0.1, shuffle=True, verbose=1, initial_epoch=0。注意这里shuffle和validation_split时,先进行split,然后才分别对train, val数据进行shuffle,所以要注意不要validation中所有类别都是同一类。

    2. 函数式模型

    在使用多输出模型、非循环有向模型或具有共享层的模型等复杂模型时,序贯模型无法解决这个问题,这时需要使用函数式模型,当然函数式模式也可以处理序贯模型问题。

    需要使用Input指定输入大小,之后通过不断使用网络层作用得到最后的输出,在Model()里指定网络的inputs, outputs即可。

    from keras.layers import Input, Dense
    from keras.models import Model
    
    # This returns a tensor
    inputs = Input(shape=(784,))
    
    # a layer instance is callable on a tensor, and returns a tensor
    x = Dense(64, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    predictions = Dense(10, activation='softmax')(x)
    
    # This creates a model that includes
    # the Input layer and three Dense layers
    model = Model(inputs=inputs, outputs=predictions)
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    model.fit(data, labels)  # starts training

    3. 常见模型

    3.1 多输入和多输出模型

    from keras.layers import Input, Embedding, LSTM, Dense
    from keras.models import Model
    
    # Headline input: meant to receive sequences of 100 integers, between 1 and 10000.
    # Note that we can name any layer by passing it a "name" argument.
    main_input = Input(shape=(100,), dtype='int32', name='main_input')
    
    # This embedding layer will encode the input sequence
    # into a sequence of dense 512-dimensional vectors.
    x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)
    
    # A LSTM will transform the vector sequence into a single vector,
    # containing information about the entire sequence
    lstm_out = LSTM(32)(x)
    
    auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
    
    auxiliary_input = Input(shape=(5,), name='aux_input')
    x = keras.layers.concatenate([lstm_out, auxiliary_input])
    
    # We stack a deep densely-connected network on top
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    
    # And finally we add the main logistic regression layer
    main_output = Dense(1, activation='sigmoid', name='main_output')(x)
    
    # 两个输入,两个输出
    model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])
    model.compile(optimizer='rmsprop', loss='binary_crossentropy',
                  loss_weights=[1., 0.2])
    model.fit([headline_data, additional_data], [labels, labels],
              epochs=50, batch_size=32)

    因为前面指定了输入、输出层的名字,可以通过字典去传递相关参数:

    # 在complie时,要配置output使用的loss,以及多个输出的loss权重
    model.compile(optimizer='rmsprop',
                  loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
                  loss_weights={'main_output': 1., 'aux_output': 0.2})
    
    # 在fit时,要给input数据,给output标签,这样才能训练
    model.fit({'main_input': headline_data, 'aux_input': additional_data},
              {'main_output': labels, 'aux_output': labels},
              epochs=50, batch_size=32)

    3.2 共享层

    任务:判断两条微博是否来自同一个人,需要同时输入两个数据,我们想利用一个共享层同时处理这两条数据:

    a = Input(shape=(32, 32, 3))
    b = Input(shape=(64, 64, 3))
    
    conv = Conv2D(16, (3, 3), padding='same')
    conved_a = conv(a)
    
    # Only one input so far, the following will work:
    assert conv.input_shape == (None, 32, 32, 3)
    
    conved_b = conv(b)
    # now the `.input_shape` property wouldn't work, but this does:
    

    同时用一个conv去卷积,需要加上以下两句,表示不同结点:

    assert conv.get_input_shape_at(0) == (None, 32, 32, 3)
    assert conv.get_input_shape_at(1) == (None, 64, 64, 3)

    3.3 inception模型

    将多个卷积操作合并。

    from keras.layers import Conv2D, MaxPooling2D, Input
    
    input_img = Input(shape=(256, 256, 3))
    
    tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)
    
    tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
    tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)
    
    tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img)
    tower_3 = Conv2D(64, (1, 1), padding='same', activation='relu')(tower_3)
    
    output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)

    3.4 残差连接

    from keras.layers import Conv2D, Input
    
    # input tensor for a 3-channel 256x256 image
    x = Input(shape=(256, 256, 3))
    # 3x3 conv with 3 output channels (same as input channels)
    y = Conv2D(3, (3, 3), padding='same')(x)
    # this returns x + y.
    z = keras.layers.add([x, y])

    3.5 共享视觉模型

    from keras.layers import Conv2D, MaxPooling2D, Input, Dense, Flatten
    from keras.models import Model
    
    # First, define the vision modules
    digit_input = Input(shape=(27, 27, 1))
    x = Conv2D(64, (3, 3))(digit_input)
    x = Conv2D(64, (3, 3))(x)
    x = MaxPooling2D((2, 2))(x)
    out = Flatten()(x)
    
    vision_model = Model(digit_input, out)
    
    # Then define the tell-digits-apart model
    digit_a = Input(shape=(27, 27, 1))
    digit_b = Input(shape=(27, 27, 1))
    
    # The vision model will be shared, weights and all
    out_a = vision_model(digit_a)
    out_b = vision_model(digit_b)
    
    concatenated = keras.layers.concatenate([out_a, out_b])
    out = Dense(1, activation='sigmoid')(concatenated)
    
    classification_model = Model([digit_a, digit_b], out)

    3.6 视觉问答模型

    from keras.layers import Conv2D, MaxPooling2D, Flatten
    from keras.layers import Input, LSTM, Embedding, Dense
    from keras.models import Model, Sequential
    
    # First, let's define a vision model using a Sequential model.
    # This model will encode an image into a vector.
    vision_model = Sequential()
    vision_model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(224, 224, 3)))
    vision_model.add(Conv2D(64, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(128, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Flatten())
    
    # Now let's get a tensor with the output of our vision model:
    image_input = Input(shape=(224, 224, 3))
    encoded_image = vision_model(image_input)
    
    # Next, let's define a language model to encode the question into a vector.
    # Each question will be at most 100 word long,
    # and we will index words as integers from 1 to 9999.
    question_input = Input(shape=(100,), dtype='int32')
    embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
    encoded_question = LSTM(256)(embedded_question)
    
    # Let's concatenate the question vector and the image vector:
    merged = keras.layers.concatenate([encoded_question, encoded_image])
    
    # And let's train a logistic regression over 1000 words on top:
    output = Dense(1000, activation='softmax')(merged)
    
    # This is our final model:
    vqa_model = Model(inputs=[image_input, question_input], outputs=output)
    
    # The next stage would be training this model on actual data.

    3.7 视频问答模型

    在原来的视觉模型加入LSTM,就可以解决视频问题。

    from keras.layers import TimeDistributed
    
    video_input = Input(shape=(100, 224, 224, 3))
    # This is our video encoded via the previously trained vision_model (weights are reused)
    encoded_frame_sequence = TimeDistributed(vision_model)(video_input)  # the output will be a sequence of vectors
    encoded_video = LSTM(256)(encoded_frame_sequence)  # the output will be a vector
    
    # This is a model-level representation of the question encoder, reusing the same weights as before:
    question_encoder = Model(inputs=question_input, outputs=encoded_question)
    
    # Let's use it to encode the question:
    video_question_input = Input(shape=(100,), dtype='int32')
    encoded_video_question = question_encoder(video_question_input)
    
    # And this is our video question answering model:
    merged = keras.layers.concatenate([encoded_video, encoded_video_question])
    output = Dense(1000, activation='softmax')(merged)
    video_qa_model = Model(inputs=[video_input, video_question_input], outputs=output)

    4. API

    4.1 compile

    model.compile()中提供了loss_weights用于多个loss进行加权,如loss_weight=[0.8, 0.2]。

    compile(self, optimizer, loss, metrics=None, loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)

    4.2 fit

    model.fit()中class_weight将不同类别给予不同损失函数权重,steps_per_epoch表示一个epoch里需要多少次迭代,默认为None时值为(nb_samples + batch_size - 1) // batch_size。validation_data提供验证集,可以覆盖validation_split。

    fit(self, x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None, validation_steps=None)

    利用Python的生成器,逐个生成数据的batch并进行训练。生成器与模型将并行执行以提高效率。例如,该函数允许我们在CPU上进行实时的数据预处理,同时在GPU上进行模型训练:

    • steps_per_epoch: 1个epoch中应包含的迭代数
    • workers: 处理数据进程数
    • max_q_size:生成器队列的最大容量
    fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)

    例子:

    def generate_arrays_from_file(path):
        while 1:
        f = open(path)
        for line in f:
            # create numpy arrays of input data
            # and labels, from each line in the file
            x1, x2, y = process_line(line)
            yield ({'input_1': x1, 'input_2': x2}, {'output': y})
        f.close()
    
    model.fit_generator(generate_arrays_from_file('/my_file.txt'),
            steps_per_epoch=10000, epochs=10)

    predict_generator参数与fit_generator差不多,需要传入genrator, steps。

    predict_generator(self, generator, steps, max_queue_size=10, workers=1, use_multiprocessing=False, verbose=0)

    4.3 Lambda层

    使用keras.layers.core.Lambda自定义层。

    from keras.layers.core import Lambda
    
    def lambda_ctc_func(x):
    	y_pred, labels, pred_len, label_len = x
    	pred = pred[:, :, 0, :]
    	return K.ctc_batch_cost(labels, y_pred, pred_len, label_len)
    
    input_tensor, y_pred = build_model(args.img_size[0], args.num_channels)
    loss_out = Lambda(lambda_ctc_func, name="ctc_loss" )([y_pred, labels, pred_len, label_len])
    
    model = Model(inputs=[input_tensor, labels, pred_len, label_len], outputs=loss_out)
    model.compile(loss: {'ctc_loss': lambda label, loss_out: loss_out})

    compile中的loss函数需要接收两个函数,一个是传入的ground truth label,一个是网络的输出,一般loss函数通过这两者计算loss,但我们的loss计算已经在Lambda层中计算了,所以网络的输出loss_out就是最后的loss值,这里使用lambda表达式直接将这个值输出作为最后的损失值。

    另外在使用这个网络时,由于loss_out中并没有参数需要载入,我们新建模型时只需要把之前网络输出的y_pred拿出来就好了,

    model = Model(inputs=input_tensor, outputs=y_pred)
    model.load_weights('model.h5')

    4.4 BatchNormalization层

    该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1。

    keras.layers.normalization.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', moving_variance_initializer='ones', beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None)
  • 相关阅读:
    SQL必知必会-笔记(五)函数
    软件测试面试题:系统中的图片不显示如何排查原因
    windows用浏览器访问linux目录文件
    记测试工作中一次印象深刻的事
    怎么快速适应新的测试工作?
    xshell如何导出日志文件和上传文件
    jmeter+fiddler高效率整理接口脚本
    python-用requests库处理form-data格式的参数
    软件自动化测试工程师面试题集锦(4)
    shell脚本批量检查某个或多个服务的端口和进程是否正常
  • 原文地址:https://www.cnblogs.com/gr-nick/p/9141449.html
Copyright © 2011-2022 走看看