python机器学习实现人脸图片自动补全

人脸自动补全

关注公众号“轻松学编程”了解更多。

1、导包

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time
from pandas import DataFrame,Series

#导入knn模型包
from sklearn.neighbors import KNeighborsRegressor

from sklearn.linear_model import LinearRegression,Ridge,Lasso

%matplotlib inline
#绘图时可以显示中文
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

2、获取数据

#从模块自带的数据集中选取人脸数据
from sklearn.datasets import fetch_olivetti_faces

faces = fetch_olivetti_faces()
#images中存储了400张64*64像素的照片
faces.images.shape

这里写图片描述

3、数据建模

提取特征数据和目标数据

#data是images的样本特征形式数据
faces.data.shape

这里写图片描述

#目标数据分为了40类,每类分组10张照片(0-39)
np.unique(faces.target,return_counts=True)

这里写图片描述

#查看一张照片的数据维度
faces.images[0].shape

这里写图片描述

#显示一张照片
plt.imshow(faces.images[0])

这里写图片描述

#提取特征数据
train = faces.data
#提取目标数据
target = faces.target

4、拆分数据

拆分数据:将样本数据拆分成训练数据(80%)和测试数据(20%)。

  • 训练数据:特征(左半张脸) 目标(右半张脸)
  • 测试数据:特征(左半张脸) 目标(右半张脸)
X_train = []
X_test = []
y_train = []
y_test = []

for i in range(40):
    #获取每种分类的10张照片数据
    person_faces = train[target == i]
    
    #将获取的每种分类中的每张照片切分成上、下半张脸两部分
    for k in range(len(person_faces)):
        face_data = person_faces[k]
        #取照片左边
        left_face = face_data.reshape(64,64)[:,:32].ravel()
        #取照片右边
        right_face = face_data.reshape(64,64)[:,32:].ravel()
        
  #将每种分类中的前8张照片的左、右半张脸的数据分别添加到训练数据的集合中
        if k < 8:
            X_train.append(left_face)
            y_train.append(right_face)
        else:
  #将每种分类中的后2张照片的左、右半张脸的数据分别添加到测试数据的集合中
            X_test.append(left_face)
            y_test.append(right_face)

6、模型评估

建一个DataFrame表格

df=DataFrame(data=None,
             index=['k-近邻模型',
                      '普通线性回归(linear)',
                      '岭回归(Ridge)',
                      'lasso回归'],
            columns=['评分','训练时间(s)','k值/alpha',])

knn模型

score = 0
k=0
for i in range(1,40):
    knn = KNeighborsRegressor(n_neighbors=i)
    start=time.time()
    knn.fit(X_train,y_train)
    end=time.time()
    s=knn.score(X_test,y_test)
    if score < s:
        score = s
        k=i
ktime = end-start
df.loc['k-近邻模型']=[score,ktime,k]

普通线性回归模型

score = 0
for i in range(1,10):
    linear = LinearRegression()
    start=time.time()
    linear.fit(X_train,y_train)
    end=time.time()
    s=linear.score(X_test,y_test)
    if score < s:
        score = s
ktime = end-start
df.loc['普通线性回归(linear)']=[score,ktime,None]

岭回归模型

score = 0
alpha=0
for i in range(1,10):
    ridge = Ridge(alpha=i)
    start=time.time()
    ridge.fit(X_train,y_train)
    end=time.time()
    s=ridge.score(X_test,y_test)
    if score < s:
        score = s
        alpha=i
ktime = end-start
df.loc['岭回归(Ridge)']=[score,ktime,alpha]

lasso模型

score = 0
alpha=0
for i in range(1,10):
    lasso = Lasso(alpha=i)
    start=time.time()
    lasso.fit(X_train,y_train)
    end=time.time()
    s=lasso.score(X_test,y_test)
    if abs(score) < abs(s):
        score = s
        alpha=i
ktime = end-start
df.loc['lasso回归']=[score,ktime,alpha]
df

这里写图片描述

从表格可以看出knn模型和岭回归模型对预测结果较为精准。

7、绘图

#将预测的缺失部分和测试数据整合一起显示
plt.figure(figsize=(8,6))
#图片标题
title=['true_img','knn_img','linear_img','lasso_img','ridge_img']
#预测4张照片
for i in range(4):
    #预测测试数据中照片缺失的部分
    knn_y = knn.predict([X_test[i]])
    linear_y = linear.predict([X_test[i]])
    ridge_y = ridge.predict([X_test[i]])
    lasso_y = lasso.predict([X_test[i]])
    #合并原始照片
    true_img=np.concatenate((X_test[i].reshape(64,32),
    					   y_test[i].reshape(64,32)),axis=1)
    #合并预测照片
    knn_img=np.concatenate((X_test[i].reshape(64,32),
    					  knn_y[0].reshape(64,32)),axis=1)
    linear_img=np.concatenate((X_test[i].reshape(64,32),
    						linear_y[0].reshape(64,32)),axis=1)
    lasso_img=np.concatenate((X_test[i].reshape(64,32),
    						lasso_y[0].reshape(64,32)),axis=1)
    ridge_img=np.concatenate((X_test[i].reshape(64,32),
    						ridge_y[0].reshape(64,32)),axis=1)
    
    index=[true_img,knn_img,linear_img,lasso_img,ridge_img]
    #一行显示5张照片做对比
    for j in range(5):
        axes = plt.subplot(5,5,(j+1)+i*5)
        axes.imshow(index[j])
        if i < 1:
            axes.set_title(title[j])

这里写图片描述

经过对比使用岭回归(ridge)模型对照片右半部分补全效果较好。

后记

【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。

也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!

公众号

公众号

赞赏码

关注我,我们一起成长~~

posted @ 2018-07-28 15:48  轻松学编程  阅读(638)  评论(0编辑  收藏  举报