算法集锦(14)|图像识别| 图像识别算法的罗夏测试
随着对基于深度学习的图像识别算法的大量研究与应用,我们倾向于将各种各样的算法组合起来快速进行图片识别和标注。优化后的算法在内存的使用和模型训练上表现越来越好,但当这些算法应用于模糊的、意义不确定的图像时,它们的表现又会如何呢?
为了更好地了解各个卷积神经网络算法在应用层面上的细微差别和趋势,我们将其应用到罗夏墨迹测试(Rorschach Test)上。
方法很简单:设定我的预测,明确我对每一个预测的理解,这样我就可以用正确的工具来完成接下来的工作。
罗夏墨迹测试
罗夏墨迹测验是现代心理测验中最主要的投射测验,于1921年由瑞士精神病学家洛夏(H.Rorschach)所研制,是侧重于精神动力学理论来研究人格的一种方法。所谓投射测验,通常是指观察个人对一些模糊的或者无机构材料所做出的反应,在这些反应中自然包含了个人的行为特征模式。
罗夏测验材料由10张结构模棱两可的墨迹图组成,其中5张全为黑色,2张是在黑色和灰色图外加了红色墨迹,另3张全为彩色。施测时按10张图片顺序一张一张地交给受试者,要他说出在图中看到了什么,不限时间,尽可能多地说出来,这一阶段称联想阶段;看完10张图,再从头对每一回答询问,问受试者看到是整图还是图中的哪一部分,为什么这些部位像所说的内容,并记录回答内容,这一阶段称询问阶段。洛夏测验记分(编码)和解释目前主要依据美国的Exner的综合系统,该系统包括了大样本的儿童(5岁起)和成人常模资料、分析的解释策略和步骤,是用于正常和病理人格的理论和临床研究的主要洛夏测验分析系统。
在本例中,我们将罗夏墨迹测试的图片作为测试集,使用各种经预训练的算法对其进行预测分类。
算法分类器
为了对罗夏测试的各个图片进行分类,我们尝试了以下算法:
- ResNet50
- VGG16
- VGG19
- InceptionV3
- InceptionResNetV2
- Xception
- MobileNet
- MobileNetV2
- DenseNet
- NASNet
各个算法模型的结构及权重特点如下表所示。
除了内存使用和可训练参数,每个参数的实现细节都有很大的不同。与其挖掘每个结构的特殊性,不如让看看它们是如何处理这些模糊的、意义不明的数据的。
测试结果
总的来说,我们的目标是对预测和预测背后的机理有一个快速的认识。因此点,我们将预测分值靠前的分为一组,并将它们的得分相加。对每个标签这样做可以很好地代表每个分类器的预测结果,并让我们对每张卡片的相对置信度有很好的了解。
例如,InceptionResNetV2、nasnetbig和DensetNet201认为卡片1是一架战机(分数分别为88.3%、46.2%和18.6%)。我把它加起来是153.1的无量纲分数。现在,我可以在分类器之间比较这个分数,看看哪一个表现得最好。
- 卡片1~3
最优的预测结果分别为战机、时钟和皮书套。
Card 1:
warplane 153.05
wall_clock 75.41
letter_opener 47.29
lampshade 33.13
buckeye 28.95
jigsaw_puzzle 23.19
paper_towel 22.51
birdhouse 11.50
Card 2:
cock 72.84 # <--- Rooster. They mean rooster.
lampshade 59.99
brassiere 59.47
velvet 43.84
earthstar 41.42
mask 29.46
candle 21.84
tray 19.30
wall_clock 18.41
hair_slide 17.84
vase 11.44
Card 3:
book_jacket 325.35 # <--- No idea what's going on here.
coffee_mug 62.61
chocolate_sauce 45.00
candle 32.68
ant 25.81
matchstick 24.02
jersey 16.94
- 卡片4~7
卡片4到7则被理解成烟、宇宙飞船和虫子等。
Card 4:
volcano 101.76
fountain 72.11
space_shuttle 32.72
hen-of-the-woods 29.40
pitcher 28.28
vase 25.00
king_crab 23.99
wall_clock 18.25
triumphal_arch 11.04
Card 5: # <--- Bugs. Definitely bugs.
isopod 106.54
king_crab 83.67
ant 61.58
long-horned_beetle 32.23
tick 30.05
hip 26.32
rhinoceros_beetle 14.52
Card 6:
space_shuttle 174.48
warplane 155.58
conch 104.73
missile 63.71
airship 57.73
fountain 11.57
Card 7:
missile 195.66
parachute 52.52
projectile 42.31
space_shuttle 31.18
hip 29.89
geyser 20.92
warplane 17.50
- 卡片8~10
对于这些复杂图像的识别就比较难以理解了,比如第10张卡片竟被认为是托盘。
Card 8:
fountain 189.59
parachute 98.27
umbrella 94.61
pencil_sharpener 63.27
spoonbill 51.08
poncho 45.19
coral_fungus 12.05
shovel 10.12
Card 9:
missile 238.45
fountain 64.82
parachute 48.21
volcano 44.77
paper_towel 41.59
lampshade 13.48
Card 10:
tray 229.22
handkerchief 151.63
conch 77.94
feather_boa 60.34
rapeseed 15.95
当然,我们可以更深入地研究每一个预测的平均置信度。下面是卡片1的一些示例数据。
代 码
为了给每张卡片设置标签,我们首先加载 Pandas、NumPy和Keras 等图像预处理库:
from keras.preprocessing import image
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
import keras.backend as K
import numpy as np
import pandas as pd
import json
然后我们创建一个函数来返回一个dataframe,其中包含每个库前10个结果的分数,以便快速地组合每个图像的分数:
def getLabels(model, dims, pi, dp):
"""
Returns the top 10 labels, given a model, image dimensions,
preprocess_input() function, and the labels inside decode_predictions().
"""
df = pd.DataFrame()
for img_path in images:
# Resize image array
image = load_img(img_path, target_size=(dims, dims))
image = img_to_array(image)
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
image = pi(image)
# Predict what is in the image
yhat = model.predict(image)
# return the top 10 labels
labels = dp(yhat, top=10)[0]
# create empty list and counter
labellist = []
counter = 0
# get labels for each image
for label in labels:
# Display the score of the label
print('%s (%.2f%%)' % (label[1], label[2]*100))
# Add image results to list
labellist.append(
{"labelnumber":counter,
"labelname" :label[1],
"pct" :'%.2f%%' % (label[2]*100),
"image" :img_path})
counter = counter + 1
# Add to dataframe
df_row = pd.Series()
df_row = pd.read_json(json.dumps(labellist), typ='frame', orient='records')
df = df.append(df_row,ignore_index=True)
print("------------")
return df
现在,我们有了一个快速评估每个库的方法。
# ...
# ResNet50 Rorschach assessment
from keras.applications.resnet50 import ResNet50
from keras.applications.resnet50 import preprocess_input
from keras.applications.resnet50 import decode_predictions
model = ResNet50()
df = getLabels(model, 224, preprocess_input, decode_predictions)
df.to_csv('results_resnet50.csv', index=False)
# ----------
# VGG16 Rorschach assessment
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.applications.vgg16 import decode_predictions
model = VGG16()
df = getLabels(model, 224, preprocess_input, decode_predictions)
df.to_csv('results_vgg16.csv', index=False)
# ...
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 从亲身经历谈谈如何用Git分支解决项目生产实践中的痛点
- mysql数据库基础命令(一)
- Linux系统Logrotate服务介绍
- python五十四课——datetime模块
- python五十五课——calendar模块
- python五十六课——正则表达式(常用函数之match)
- python五十六课——正则表达式(常用函数之search())
- python五十六课——正则表达式(常用函数之findall)
- python五十七课——正则表达式(元字符)
- python五十七课——正则表达式(边界字符)
- python五十七课——正则表达式(多个字符)
- python五十八课——正则表达式(分组)
- python五十八课——正则表达式(替换)
- 配置Tomcat使用https协议(单向认证)
- python五十八课——正则表达式(切割)