Files
machine_learning_projects/3.宝可梦数据集分析/平时作业/face_recognition.ipynb
T
less IS more 36115579e0 平时实践任务
Signed-off-by: less IS more <13190735+wnflt@user.noreply.gitee.com>
2023-07-17 01:38:43 +00:00

664 lines
20 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 读取图像数据"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"import numpy as np\n",
"import os\n",
"import cv2"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def getimgnames(path=None):\n",
" \"\"\"\n",
" 获取指定文件夹中的JPG图片名称(含路径)\n",
" :param path: 指定文件夹\n",
" :return: path中的所有JPG图片名称(含路径,例如:./path/image1.jpg\n",
" \"\"\"\n",
" imgnames = []\n",
" filenames = os.listdir(path) # 获取path中的所有文件名\n",
" for i in filenames:\n",
" if re.findall('^\\d+\\.jpg$', i) != []: # 在所有文件名中找出JPG图片名称\n",
" imgnames.append(os.path.join(path, i)) # 将图片名称和路径合并、保存\n",
" return imgnames"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"class GetImgData:\n",
"\n",
" def __init__(self, dir='data//gray_face_images'):\n",
" self.dir = dir\n",
"\n",
" def onehot(self, indexlist=None):\n",
" b = np.zeros([len(indexlist), max(indexlist) + 1])\n",
" b[np.arange(len(indexlist)), indexlist] = 1\n",
" return b.tolist()\n",
"\n",
" def getfileandlabel(self):\n",
" dicdir = {name: os.path.join(self.dir, name) for name in os.listdir(self.dir) if os.path.isdir(os.path.join(self.dir, name))}\n",
" ## 生成字典,key为文件夹名称,value为文件夹路径\n",
" # ditcir = {}\n",
" # for name in os.listdir(self.dir):\n",
" # if os.path.isdir(os.path.join(self.dir, name)):\n",
" # dicdir[name] = os.path.join(self.dir, name)\n",
" namelist, pathlist = dicdir.keys(), dicdir.values()\n",
" indexlist = list(range(len(namelist)))\n",
" return list(zip(pathlist, self.onehot(indexlist))), dict(zip(indexlist, namelist))\n",
"\n",
" def readimg(self):\n",
" dir_label, num_name = self.getfileandlabel()\n",
" imgs = []\n",
" labels = []\n",
" for path, label in dir_label:\n",
" for imgname in getimgnames(path):\n",
" img = cv2.imread(imgname)[:, :, 0:1]\n",
" imgs.append(img)\n",
" labels.append(label)\n",
" data = np.array(imgs, dtype=np.float32) / 255\n",
" y = np.array(labels, dtype=np.float32)\n",
" return data, y, num_name"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[[[0.30588236]\n",
" [0.32156864]\n",
" [0.25490198]\n",
" ...\n",
" [0.2901961 ]\n",
" [0.30980393]\n",
" [0.30980393]]\n",
"\n",
" [[0.23529412]\n",
" [0.23529412]\n",
" [0.21568628]\n",
" ...\n",
" [0.24705882]\n",
" [0.21960784]\n",
" [0.30980393]]\n",
"\n",
" [[0.19215687]\n",
" [0.17254902]\n",
" [0.18431373]\n",
" ...\n",
" [0.27058825]\n",
" [0.2509804 ]\n",
" [0.28235295]]\n",
"\n",
" ...\n",
"\n",
" [[0.17254902]\n",
" [0.16078432]\n",
" [0.14509805]\n",
" ...\n",
" [0.18431373]\n",
" [0.1764706 ]\n",
" [0.18431373]]\n",
"\n",
" [[0.13725491]\n",
" [0.15294118]\n",
" [0.19215687]\n",
" ...\n",
" [0.16862746]\n",
" [0.1764706 ]\n",
" [0.19215687]]\n",
"\n",
" [[0.18039216]\n",
" [0.14901961]\n",
" [0.15294118]\n",
" ...\n",
" [0.13333334]\n",
" [0.18039216]\n",
" [0.15686275]]]\n",
"\n",
"\n",
" [[[0.4117647 ]\n",
" [0.36862746]\n",
" [0.3647059 ]\n",
" ...\n",
" [0.30980393]\n",
" [0.3372549 ]\n",
" [0.3019608 ]]\n",
"\n",
" [[0.36078432]\n",
" [0.3647059 ]\n",
" [0.29803923]\n",
" ...\n",
" [0.30588236]\n",
" [0.29411766]\n",
" [0.31764707]]\n",
"\n",
" [[0.35686275]\n",
" [0.27450982]\n",
" [0.3019608 ]\n",
" ...\n",
" [0.3019608 ]\n",
" [0.29803923]\n",
" [0.28627452]]\n",
"\n",
" ...\n",
"\n",
" [[0.18431373]\n",
" [0.15686275]\n",
" [0.16078432]\n",
" ...\n",
" [0.19607843]\n",
" [0.22352941]\n",
" [0.2627451 ]]\n",
"\n",
" [[0.14117648]\n",
" [0.15294118]\n",
" [0.14509805]\n",
" ...\n",
" [0.23529412]\n",
" [0.25882354]\n",
" [0.28235295]]\n",
"\n",
" [[0.16078432]\n",
" [0.13725491]\n",
" [0.13725491]\n",
" ...\n",
" [0.16862746]\n",
" [0.20784314]\n",
" [0.22745098]]]\n",
"\n",
"\n",
" [[[0.5372549 ]\n",
" [0.5137255 ]\n",
" [0.42352942]\n",
" ...\n",
" [0.2 ]\n",
" [0.2 ]\n",
" [0.20784314]]\n",
"\n",
" [[0.52156866]\n",
" [0.45490196]\n",
" [0.34117648]\n",
" ...\n",
" [0.18039216]\n",
" [0.2 ]\n",
" [0.23529412]]\n",
"\n",
" [[0.5137255 ]\n",
" [0.38431373]\n",
" [0.3254902 ]\n",
" ...\n",
" [0.1882353 ]\n",
" [0.1764706 ]\n",
" [0.1764706 ]]\n",
"\n",
" ...\n",
"\n",
" [[0.14117648]\n",
" [0.21176471]\n",
" [0.27058825]\n",
" ...\n",
" [0.07843138]\n",
" [0.09803922]\n",
" [0.07058824]]\n",
"\n",
" [[0.21960784]\n",
" [0.2627451 ]\n",
" [0.29803923]\n",
" ...\n",
" [0.07450981]\n",
" [0.09411765]\n",
" [0.09019608]]\n",
"\n",
" [[0.28235295]\n",
" [0.2784314 ]\n",
" [0.27450982]\n",
" ...\n",
" [0.08627451]\n",
" [0.07450981]\n",
" [0.08627451]]]\n",
"\n",
"\n",
" ...\n",
"\n",
"\n",
" [[[0.18039216]\n",
" [0.16470589]\n",
" [0.16078432]\n",
" ...\n",
" [0.5568628 ]\n",
" [0.54901963]\n",
" [0.5529412 ]]\n",
"\n",
" [[0.18431373]\n",
" [0.18431373]\n",
" [0.19215687]\n",
" ...\n",
" [0.5411765 ]\n",
" [0.54509807]\n",
" [0.5529412 ]]\n",
"\n",
" [[0.2 ]\n",
" [0.19215687]\n",
" [0.19215687]\n",
" ...\n",
" [0.5411765 ]\n",
" [0.54901963]\n",
" [0.5568628 ]]\n",
"\n",
" ...\n",
"\n",
" [[0.6901961 ]\n",
" [0.6862745 ]\n",
" [0.61960787]\n",
" ...\n",
" [0.11764706]\n",
" [0.11372549]\n",
" [0.12941177]]\n",
"\n",
" [[0.61960787]\n",
" [0.6784314 ]\n",
" [0.5568628 ]\n",
" ...\n",
" [0.1254902 ]\n",
" [0.1254902 ]\n",
" [0.1254902 ]]\n",
"\n",
" [[0.54509807]\n",
" [0.43137255]\n",
" [0.4862745 ]\n",
" ...\n",
" [0.11764706]\n",
" [0.10196079]\n",
" [0.11764706]]]\n",
"\n",
"\n",
" [[[0.34901962]\n",
" [0.21568628]\n",
" [0.19607843]\n",
" ...\n",
" [0.23921569]\n",
" [0.21960784]\n",
" [0.20784314]]\n",
"\n",
" [[0.24313726]\n",
" [0.18431373]\n",
" [0.19607843]\n",
" ...\n",
" [0.30588236]\n",
" [0.22745098]\n",
" [0.23137255]]\n",
"\n",
" [[0.22352941]\n",
" [0.1764706 ]\n",
" [0.19607843]\n",
" ...\n",
" [0.39215687]\n",
" [0.25490198]\n",
" [0.18431373]]\n",
"\n",
" ...\n",
"\n",
" [[0.7372549 ]\n",
" [0.7294118 ]\n",
" [0.70980394]\n",
" ...\n",
" [0.21568628]\n",
" [0.20784314]\n",
" [0.21960784]]\n",
"\n",
" [[0.7254902 ]\n",
" [0.69411767]\n",
" [0.69803923]\n",
" ...\n",
" [0.23529412]\n",
" [0.16862746]\n",
" [0.19607843]]\n",
"\n",
" [[0.68235296]\n",
" [0.6784314 ]\n",
" [0.6431373 ]\n",
" ...\n",
" [0.19215687]\n",
" [0.16078432]\n",
" [0.16470589]]]\n",
"\n",
"\n",
" [[[0.50980395]\n",
" [0.3647059 ]\n",
" [0.19607843]\n",
" ...\n",
" [0.41568628]\n",
" [0.34901962]\n",
" [0.24313726]]\n",
"\n",
" [[0.50980395]\n",
" [0.29803923]\n",
" [0.1764706 ]\n",
" ...\n",
" [0.44705883]\n",
" [0.40784314]\n",
" [0.31764707]]\n",
"\n",
" [[0.4509804 ]\n",
" [0.25882354]\n",
" [0.18039216]\n",
" ...\n",
" [0.48235294]\n",
" [0.47058824]\n",
" [0.3764706 ]]\n",
"\n",
" ...\n",
"\n",
" [[0.76862746]\n",
" [0.7647059 ]\n",
" [0.7490196 ]\n",
" ...\n",
" [0.12156863]\n",
" [0.13333334]\n",
" [0.14117648]]\n",
"\n",
" [[0.76862746]\n",
" [0.7529412 ]\n",
" [0.7254902 ]\n",
" ...\n",
" [0.11764706]\n",
" [0.12941177]\n",
" [0.1254902 ]]\n",
"\n",
" [[0.7529412 ]\n",
" [0.7411765 ]\n",
" [0.7176471 ]\n",
" ...\n",
" [0.11372549]\n",
" [0.11372549]\n",
" [0.1254902 ]]]]\n"
]
}
],
"source": [
"if __name__ == '__main__':\n",
" getimgdata = GetImgData()\n",
" data, y, num_name = getimgdata.readimg()\n",
" print(data)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from getimgdata import GetImgData\n",
"from random import sample\n",
"from sklearn.model_selection import train_test_split\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"## 兼容v1\n",
"tf.compat.v1.disable_eager_execution()\n",
"\n",
"getimgdata = GetImgData(dir='data//gray_face_images')\n",
"data, y, num_name = getimgdata.readimg()\n",
"X_tr, X_te, y_tr, y_te = train_test_split(data, y, test_size=0.2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 构建CNN神经网络"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"class CnnNet:\n",
"\n",
" def __init__(self, imgs=None, labels=None, keep_prob_5=0.5, modeldir=None):\n",
" tf.compat.v1.reset_default_graph() # 重置计算图\n",
" self.imgs = imgs\n",
" self.labels = labels\n",
" self.modeldir = modeldir\n",
" self.size = imgs.shape[1]\n",
" self.keep_prob_5 = keep_prob_5\n",
" self.outnode = labels.shape[1]\n",
" self.x = tf.compat.v1.placeholder(tf.float32, [None, self.size, self.size, 1], name='x_data')\n",
" self.y_ = tf.compat.v1.placeholder(tf.float32, [None, self.outnode])\n",
"\n",
" def weightVariable(self, shape): # 权值数组W\n",
" init = tf.compat.v1.random_normal(shape, stddev=0.01)\n",
" return tf.compat.v1.Variable(init)\n",
"\n",
" def biasVariable(self, shape): # 偏置项数组b\n",
" init = tf.compat.v1.random_normal(shape)\n",
" return tf.Variable(init)\n",
"\n",
" def conv2d(self, x, W): # 卷积\n",
" return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')\n",
"\n",
" def maxPool(self, x): # max池化\n",
" return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')\n",
"\n",
" def dropout(self, x, keep): # 随机让某些权重不更新,保持某个数\n",
" return tf.nn.dropout(x, keep)\n",
"\n",
" def cnnLayer(self):\n",
" \"\"\"\n",
" cnn神经网络结构\n",
" :return:\n",
" \"\"\"\n",
" # ===第一次卷积&池化====\n",
" W1 = self.weightVariable(shape=[3, 3, 1, 32])\n",
" b1 = self.biasVariable([32])\n",
" conv1 = tf.nn.relu(self.conv2d(self.x, W1) + b1)\n",
" pool1 = self.maxPool(conv1)\n",
" drop1 = self.dropout(pool1, self.keep_prob_5)\n",
"\n",
" # ===第二次卷积&池化====\n",
" W2 = self.weightVariable([3, 3, 32, 64])\n",
" b2 = self.biasVariable([64])\n",
" conv2 = tf.nn.relu(self.conv2d(drop1, W2) + b2)\n",
" pool2 = self.maxPool(conv2)\n",
" drop2 = self.dropout(pool2, self.keep_prob_5)\n",
"\n",
" # ===第三次卷积&池化====\n",
" W3 = self.weightVariable([3, 3, 64, 64])\n",
" b3 = self.biasVariable([64])\n",
" conv3 = tf.nn.relu(self.conv2d(drop2, W3) + b3)\n",
" pool3 = self.maxPool(conv3)\n",
" drop3 = self.dropout(pool3, self.keep_prob_5)\n",
"\n",
" # ===全连接层1====\n",
" Wf = self.weightVariable([8*8*64, 512])\n",
" bf = self.biasVariable([512])\n",
" drop3_flat = tf.reshape(drop3, [-1, 8*8*64])\n",
" dense = tf.nn.relu(tf.matmul(drop3_flat, Wf) + bf)\n",
" dropf = self.dropout(dense, 0.75)\n",
"\n",
" # ===输出层====\n",
" W_out = self.weightVariable([512, self.outnode])\n",
" b_out = self.biasVariable([self.outnode])\n",
" out = tf.add(tf.matmul(dropf, W_out), b_out, name='out')\n",
" return out\n",
" \n",
" def cnnTrain(self, maxiter=1000, accu=0.99, batch_size=100):\n",
" \"\"\"\n",
" 依据训练样本的模型输出与样本实际值进行模型训练\n",
" :param maxiter: 最大迭代次数\n",
" :param accu: 精度阈值,当训练精度大于accu时则停止训练\n",
" :param batch_size: 每轮训练的样本数\n",
" :return: 无返回,但是当模型精度满足要求后会将模型保存\n",
" \"\"\"\n",
" out = self.cnnLayer()\n",
" cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y_, logits=out))\n",
" train_step = tf.compat.v1.train.AdamOptimizer(0.01).minimize(cross_entropy)\n",
" acc = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(out, 1), tf.argmax(self.y_, 1)), tf.float32))\n",
"\n",
" saver = tf.compat.v1.train.Saver()\n",
" sess = tf.compat.v1.Session()\n",
" sess.run(tf.compat.v1.global_variables_initializer()) # 执行变量初始化操作\n",
" for n in range(maxiter):\n",
" ind = sample(range(len(self.imgs)), batch_size)\n",
" batch_x = self.imgs[ind]\n",
" batch_y = self.labels[ind]\n",
" sess.run(train_step, feed_dict={self.x: batch_x, self.y_: batch_y})\n",
" if n%100 == 0:\n",
" acc_tr = sess.run(acc, feed_dict={self.x: batch_x, self.y_: batch_y})\n",
" print('轮数:', n, ' the train accuracy is :', acc_tr)\n",
" if (acc_tr > accu) and (n >= 499):\n",
" saver.save(sess, self.modeldir)\n",
" break\n",
" elif n == (maxiter-1):\n",
" saver.save(sess, self.modeldir)\n",
" sess.close()\n",
"\n",
" def predict(self, test_x=None):\n",
" \"\"\"\n",
" 预测函数,导入已训练好的模型后再将新样本数据放入,进行模型预测\n",
" :param test_x: 测试样本的自变量\n",
" :return: 模型对测试样本的预测结果\n",
" 1: 预测结果(数字标签:0,1,2,3,4,5,...\n",
" pre: 样本属于各类别的概率,形如:[[0.1, 0.1, 0.0, 0.0, 0.0, 0.8]]\n",
" \"\"\"\n",
" out = self.cnnLayer()\n",
" with tf.compat.v1.Session() as sess:\n",
" saver = tf.compat.v1.train.Saver()\n",
" saver.restore(sess, self.modeldir)\n",
" graph = tf.get_default_graph()\n",
" x = graph.get_tensor_by_name('x_data:0')\n",
" pre = sess.run(out, feed_dict={x: test_x})\n",
" acc_te = sum(np.argmax(pre, 1) == np.argmax(y_te, 1)) / len(pre)\n",
" return np.argmax(pre, 1), acc_te"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 模型训练"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"轮数: 0 the train accuracy is : 0.19\n",
"轮数: 100 the train accuracy is : 0.88\n",
"轮数: 200 the train accuracy is : 0.97\n",
"轮数: 300 the train accuracy is : 0.97\n",
"轮数: 400 the train accuracy is : 0.99\n",
"轮数: 500 the train accuracy is : 0.94\n",
"轮数: 600 the train accuracy is : 0.96\n",
"轮数: 700 the train accuracy is : 0.97\n",
"轮数: 800 the train accuracy is : 0.96\n",
"轮数: 900 the train accuracy is : 1.0\n"
]
}
],
"source": [
"cnn_net = CnnNet(imgs=X_tr, labels=y_tr, modeldir='temp/train_model')\n",
"cross = cnn_net.cnnTrain()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 模型预测"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:From D:\\TEMP\\ipykernel_17504\\2843680607.py:26: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n",
"\n",
"WARNING:tensorflow:From D:\\TEMP\\ipykernel_17504\\2843680607.py:29: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.\n",
"INFO:tensorflow:Restoring parameters from temp/train_model\n",
"WARNING:tensorflow:From D:\\TEMP\\ipykernel_17504\\2843680607.py:113: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.\n",
"\n",
"the test accuracy is : 0.9845201238390093\n"
]
}
],
"source": [
"cnn_net = CnnNet(imgs=X_tr, labels=y_tr, modeldir='temp/train_model')\n",
"pre, acc_te = cnn_net.predict(test_x=X_te)\n",
"print('the test accuracy is :', acc_te)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.9 ('venv': venv)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.9"
},
"vscode": {
"interpreter": {
"hash": "a82d1522e399fc49d60c7b85358aba15d27930532737449decaece807d60f8db"
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}