深度学习技术已经在多个领域展现出其强大的能力,从手机的面部识别到自动驾驶汽车,深度学习的应用无处不在。本文将带了解如何将深度学习应用于一个有趣的问题——年龄检测。
如果最近学习或阅读了关于深度学习的内容,并希望将新技能付诸实践,那么实践问题是一个理想的起点。这些实践问题提供了从零开始解决问题的经验,而且不会过于竞争。以下是应该选择一些实践问题的几个理由:
建立基础知识:总是建议,应该始终从建立正确的基础开始(考虑问题陈述和探索数据集),并大量实践。仍然看到有人在没有思考问题和理解数据的情况下就开始编码。这种方法实际上并没有探索问题和数据,因为直接关注于利用算法。
同行学习(论坛/博客):在实践问题中,参与者会在论坛或通过博客分享他们的方法,并总是愿意讨论新的方法。由于这不是一个有奖竞赛,人们不会保留意见。
实践:这些实践问题就像在处理现实生活问题之前的练习。应该首先在这里评估表现,并努力做得更好。在这段时间里,主要目标应该是充分利用工具、算法和数据集。
测试知识:这是一个尝试学到的东西的好地方,这将对非常有益。结果并不那么重要,因为这是一个实践问题。
参与黑客马拉松的第一步是理解问题。在本文中,将关注一个最近发布的实践问题:印度演员的年龄检测。可以在黑客马拉松页面上查看问题陈述,但会在这里简要提及。
任务是从他或她的面部特征预测一个人的年龄。为了简单起见,问题已经被转换为一个多类问题,类别为年轻、中年和老年。
乍一看似乎很容易,对吧?但如果查看数据,即使对人类来说也很难!让自己检查一下!以下是数据中的一些随机示例。
中年:
老年:
年轻:
但能否猜出这些?显然,这两个都是中年演员!
要解决这些问题,需要有一个系统化的方法。将在下一节中看到这一点。
现在知道了问题,让开始吧。假设已经安装了numpy、scipy、pandas、scikit-learn和keras。如果没有,请安装它们。上述文章应该可以帮助。
首先,让下载数据并将其加载到jupyter笔记本中!如果还没有被介绍;这里是实践问题的链接()。
在构建模型之前,敦促解决这个简单的练习:能编写一个脚本来随机加载一个图像到jupyter笔记本并打印它吗?(PS:不要看下面的答案!)。请在中发布代码。
以下是对这个练习的方法;像往常一样,首先导入了所有必要的模块:
% pylab inline
import os
import random
import pandas as pd
from scipy.misc import imread
然后加载了csv文件,这样可以更容易地定位文件:
root_dir = os.path.abspath('.')
data_dir = '/mnt/hdd/datasets/misc'
train = pd.read_csv(os.path.join(data_dir, 'train.csv'))
test = pd.read_csv(os.path.join(data_dir, 'test.csv'))
然后编写了一个脚本来随机选择一个图像并打印它:
i = random.choice(train.index)
img_name = train.ID[i]
img = imread(os.path.join(data_dir, 'Train', img_name))
print('Age: ', train.Class[i])
imshow(img)
这就是得到的结果:
Age: YOUNG
这个练习的目的是可以随机查看数据集,并检查在构建模型时可能面临的一些问题。以下是对可能面临的一些问题的假设:
形状变化:一张图像的形状是(66, 46),而其他图像是(102, 87)。
多个视角:有各种视角的面孔!以下是一些示例:
图像质量:一些图像被发现过于像素化。这是一个示例。
亮度和对比度的差异:检查下面的图像;它们是否让觉得解决问题变得更容易了?
目前,让只关注一个问题,即如何处理形状的变化?可以通过简单地调整图像大小来做到这一点。让加载所有图像并将它们调整为一个单一的numpy数组。
from scipy.misc import imresize
temp = []
for img_name in train.ID:
img_path = os.path.join(data_dir, 'Train', img_name)
img = imread(img_path)
img = imresize(img, (32, 32))
img = img.astype('float32') # 这将在后期帮助
temp.append(img)
train_x = np.stack(temp)
对于测试图像也类似:
temp = []
for img_name in test.ID:
img_path = os.path.join(data_dir, 'Test', img_name)
img = imread(img_path)
img = imresize(img, (32, 32))
temp.append(img.astype('float32'))
test_x = np.stack(temp)
还可以做的一件事是可以帮助构建更好的模型,即可以归一化图像。归一化图像将使训练更快。
train_x = train_x / 255.
test_x = test_x / 255.
现在让看看目标变量。还有一个练习给;能说出数据中类别的分布吗?能说这是一个高度不平衡的问题吗?
train.Class.value_counts(normalize=True)
基于数据的分布,可以创建一个简单的提交。看到大多数演员都是中年的。所以可以认为测试数据集中的所有演员都是中年的!
test['Class'] = 'MIDDLE'
test.to_csv('sub01.csv', index=False)
上传这个文件到提交页面,看看结果!
在创建一些实质性的东西之前,让将目标变量调整为形状。将把目标转换为虚拟列,这样模型就更容易消化了。以下是将如何做到这一点。
import keras
from sklearn.preprocessing import LabelEncoder
lb = LabelEncoder()
train_y = lb.fit_transform(train.Class)
train_y = keras.utils.np_utils.to_categorical(train_y)
现在来到了主要部分,构建模型!由于问题与图像处理相关,使用神经网络来解决问题是更明智的。也将为此问题构建一个简单的前馈神经网络。
首先,应该指定将在网络中使用的所有参数:
input_num_units = (32, 32, 3)
hidden_num_units = 500
output_num_units = 3
epochs = 5
batch_size = 128
然后将导入必要的keras模块:
from keras.models import Sequential
from keras.layers import Dense, Flatten, InputLayer
之后,将定义网络:
model = Sequential([
InputLayer(input_shape=input_num_units),
Flatten(),
Dense(units=hidden_num_units, activation='relu'),
Dense(units=output_num_units, activation='softmax'),
])
让看看模型是什么样子;让打印它
model.summary()
现在让编译网络,让它训练一段时间
model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(train_x, train_y, batch_size=batch_size, epochs=epochs, verbose=1)
看起来它正在训练!但还没有验证它。如果希望确保模型在它训练的数据和新的测试数据上都表现良好,验证是必要的。
让稍微调整一下代码来进行交叉验证。
model.fit(train_x, train_y, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.2)
模型似乎对第一个模型表现良好。让提交结果。
pred = model.predict_classes(test_x)
pred = lb.inverse_transform(pred)
test['Class'] = pred
test.to_csv('sub02.csv', index=False)
这是另一个简单的练习给;打印图像以及训练的模型的预测。最好在训练数据集上这样做,这样就可以检查预测和实际目标。
以下是对练习的看法:
i = random.choice(train.index)
img_name = train.ID[i]
img = imread(os.path.join(data_dir, 'Train', img_name)).astype('float32')
imshow(imresize(img, (128, 128)))
pred = model.predict_classes(train_x)
print('Original:', train.Class[i], 'Predicted:', lb.inverse_transform(pred[i]))
原始:MIDDLE 预测:MIDDLE
已经建立了一个简单的基准解决方案。还能做什么?以下是可以建议的一些建议:
一个更好的神经网络模型可以给很大的提升。可以尝试使用卷积神经网络,它更适合图像相关问题。这里有一个简单的CNN供参考。