前言
来自北邮陈老师 (微博: 爱可可 - 爱生活) 的分享陈老师每天分享很多人工智能机器学习类的资料, 本篇虽是最少人能看懂的(因为全是日语), 却是反响最热烈的大家都对内容很好奇, 所以本站组织了翻译
本文来自大人向 AI 研究所 , 是这个博客的第一篇, 也是当前唯一一篇文章文章篇幅不长, 也非面面俱到的详细教程, 主要是提供一种思路
正文
本篇是 chainerAV 女優類似画像検索公開 - Qiita 的续篇
以前文章写过, 在学习到的模型中, 输入画像用等级分类的话, 可以判断哪个女优与之相似本篇则会从全结合层的矢量特征开始, 计算 cos 相似度, 然后检索相似的画像
而且单就图像识别来讲, keras 使用起来比 Chainer 更方便, 所以安装使用 Keras 框架
(注: 使用 Keras 框架的另一个原因是 "Keras" 的五个字母包含在 "Kaiser" 当中)
数据扩张
在 Keras 中, 使用了 ImageDataGenerator, 所以可以轻松扩大数据
因为随机抽样的画像集有倾向性或偏移, 所以很少会去学习相同的全部数据, 否则很容易产生过拟合
关于 ZCA whitening 请参考以下资料:
白色化 | DEEPTONEWorks
CIFAR-10 ZCA whitening - 日記
(注: whitening 的目的是降低输入的冗余性, 希望使特征之间相关性较低, 且所有特征具有相同的方差 )
- from keras.preprocessing.image import ImageDataGenerator
- # 分别提取数据和标签, 存为两个变量
- data, label = load_data()
- datagen = ImageDataGenerator(
- zca_whitening=True,
- rotation_range=10,
- width_shift_range=0.1,
- height_shift_range=0.1,
- horizontal_flip=True)
- datagen.fit(data)
- # 把 datagen.flow 作为参数传递给模型 fit_generator, 进行动态数据扩张
- model.fit_generator(datagen.flow(data, label, batch_size=32),
- samples_per_epoch=data.shape[0], nb_epoch=100)
脸部画像正面化
前文中, 面部画面检查出后用 dlib, 这次我们要进一步提取检查出的面部画面特征, 把眼睛和嘴巴的位置正面化后进行仿射变换因为已经安装了 openface 或 facenet, 基本上可以按照原样使用
- facenet/blob/master/src/align_dlib.py
- openface/util/align-dlib.py
构造模型
因为处于学习的数据组比较少的阶段, 虽然不能调整全部的模型和超参数, 可以先如下所示使用模型
- def conv_bn_relu(x, out_ch, name):
- x = Convolution2D(out_ch, 3, 3, border_mode='same', name=name)(x)
- x = BatchNormalization(name='{}_bn'.format(name))(x)
- x = Activation('relu', name='{}_relu'.format(name))(x)
- return x
- def face_model(input_shape=(3, 224, 224), nb_classes, weights_path=None):
- inputs = Input(shape=input_shape, name='input')
- x = conv_bn_relu(inputs, 64, name='block1_conv1')
- x = conv_bn_relu(x, 64, name='block1_conv2')
- x = MaxPooling2D((2, 2), strides=(2, 2))(x)
- x = conv_bn_relu(x, 128, name='block2_conv1')
- x = conv_bn_relu(x, 128, name='block2_conv2')
- x = MaxPooling2D((2, 2), strides=(2, 2))(x)
- x = conv_bn_relu(x, 256, name='block3_conv1')
- x = conv_bn_relu(x, 256, name='block3_conv2')
- x = conv_bn_relu(x, 256, name='block3_conv3')
- x = MaxPooling2D((2, 2), strides=(2, 2))(x)
- x = conv_bn_relu(x, 512, name='block4_conv1')
- x = conv_bn_relu(x, 512, name='block4_conv2')
- x = conv_bn_relu(x, 512, name='block4_conv3')
- x = MaxPooling2D((2, 2), strides=(2, 2))(x)
- x = Flatten()(x)
- x = Dense(4096, activation='relu', name='fc1')(x)
- x = Dense(nb_classes, activation='softmax', name='predictions')(x)
- model = Model(input=inputs, output=x)
相似度计算
这次的模型中, 在最后一步之前需要提取出全连接层的特征矢量, 根据各女优提取出的特征矢量与 cos 相似度计算出画面的相似度
- import numpy as np
- from scipy.spatial.distance import cosine
- from keras.models import Model, model_from_json
- from keras.preprocessing import image
- from keras.preprocessing.image import img_to_array
- def calculate_similarity():
- # 载入模型
- model_json = open('face_model.json').read()
- base_model = model_from_json(model_json)
- base_model.load_weights('face_model.h5')
- # 提取出全连接层和 4096 维的特征矢量做成模型
- model = Model(input=base_model.input, output=base_model.get_layer('fc1').output)
- image_file = 'image.jpg'
- img = image.load_img(image_file, target_size=(96, 96))
- x = img_to_array(img)
- x = np.expand_dims(x, axis=0)
- features = model.predict(x)
- features = features.flatten().tolist()
- # actress_features 是事先计算出的各女优的特征矢量
- # 根据输入画像提取出的矢量特征与各女优的特征矢量计算 cos 相似度
- score = 1 - cosine(features, actress_features)
最后宣传一下, 本文中所述的已安装类似面部画像检索功能的网站已经做好了, 欢迎欣赏
Babelink - 好 AV 検索(搜索你喜好的 AV)
因为是成人网站, 浏览的时候请注意
(注: 我并没有要推广那种网站的意思, 主要是为了尊重原文)
来源: https://juejin.im/post/5a93a8185188257a856f6303