### 一、前言
[TFace](https://github.com/Tencent/TFace) 由腾讯优图实验室负责开源代码和维护,仓库里有很多关于人脸识别的论文。本文主要记录测试该仓训练流程的步骤和注意事项等。
### 二、Linux
不支持在 Windows 上多卡运行。默认 DIST_BACKEND: 'nccl',在 Windows上需要修改为 DIST_BACKEND: 'gloo',但是 ProcessGroupGloo does not support reduce_scatter,因此会报错。单卡应该可以通过调整代码而运行。
### 三、数据集准备
本文以 LFW (Labled Faces in the Wild) 数据集为例。
下述步骤可能省略了诸如 文件移动、复制等操作,请注意自行移动至需要的位置。
#### 1、pts_list
利用 [该文](http://luxuff.cn/archives/retinaface) 生成人脸的5个关键点信息。
#### 2、数据集划分
利用下述代码将该数据集划分为训练集、验证集、测试集:
```python
import os
import random
import math
if __name__ == "__main__":
img_path="/home/LFW/"
train_file = "./LFW_train.txt"
val_file = "./LFW_val.txt"
test_file = "./LFW_test.txt"
people = sorted(os.listdir(img_path))
p_res = []
for idx, name in enumerate(people):
images = sorted(os.listdir(os.path.join(img_path, name)))
for img in images:
r_name = os.path.join(img_path, name, img)
p_res.append([r_name, idx])
random.seed(1987)
random.shuffle(p_res)
process = [train_file, 0, math.ceil(len(p_res)*0.8), math.ceil(len(p_res)*0.8)-1,\
val_file, math.ceil(len(p_res)*0.8), math.ceil(len(p_res)*0.9), math.ceil(len(p_res)*0.9)-1,\
test_file, math.ceil(len(p_res)*0.9), len(p_res), len(p_res)-1]
print(process)
for i in range(0, 12, 4):
print(process[i])
with open(process[i], "w") as f:
start, end, last = process[i+1], process[i+2], process[i+3]
for k in range(start, end):
if k<last:
print(p_res[k][0], p_res[k][1], file=f, end="\n")
else:
print(p_res[k][0], p_res[k][1], file=f, end="")
```
划分后的文件长这样:
```language
/home/LFW/JK_Rowling/JK_Rowling_0006.jpg 2265
/home/LFW/Tim_Henman/Tim_Henman_0014.jpg 5363
/home/LFW/Reese_Witherspoon/Reese_Witherspoon_0003.jpg 4553
/home/LFW/Zhu_Rongji/Zhu_Rongji_0008.jpg 5738
/home/LFW/Aaron_Eckhart/Aaron_Eckhart_0001.jpg 2
/home/LFW/Luis_Horna/Luis_Horna_0006.jpg 3396
```
每行分别含有图片路径、对应的标签。
#### 3、tfrecord 格式文件转换
利用提供的 img2tfrecord.py 脚本将图片转换为 tfrecord 格式:
注意进行下述修改:
```python
#第29行
#lmk = np.array([float(x) for x in line[1: -1]], dtype=np.float32)
lmk = np.array([float(x) for x in line[1:]], dtype=np.float32)
```
然后执行:
```python
python img2tfrecord.py --img_list ./LFW_img_list.txt --pts_list LFW_5p.txt --tfrecords_name LFW_tfrecords
```
如果报错 “AttributeError: module 'tensorflow' has no attribute 'python_io'”,这是因为 tensorflow 的版本问题,tensorflow2.x 中的 python_io 已经改地方了,将 img2tfrecord.py 中的代码进行如下修改再执行即可:
```python
#第99行左右
#cur_shard_writer = tf.python_io.TFRecordWriter(cur_shard_path)
cur_shard_writer = tf.compat.v1.python_io.TFRecordWriter(cur_shard_path)
```
#### 4、index 文件转换:
```python
python convert_new_index.py --old ./LFW_train.txt --tfr_index ./LFW_tfrecords/LFW_tfrecords.index --new TFR_LFW_train_tf.txt
```
\-\-new 参数指定的文件名需要以 “TFR” 开头,因为 dataloader 里面会以这种方式判断是否使用 tfrecord 格式解析文件。
### 四、train
修改 train.yaml 文件:
```language
DATA_ROOT: '/home/s03/tanhualin/TFace-master/recognition/tools/' # the parent root where your train/val/test data are stored
INDEX_ROOT: '/home/s03/tanhualin/TFace-master/recognition/tools/'
DATASETS: # the dataset index name
- name: TFR_LFW_train_tf
```
直接运行:
```python
python train.py
```
中间需要的各种包请自行 pip install,torch 和 torchvision 采用如下版本。
https://download.pytorch.org/whl/cu111/torch-1.9.1%2Bcu111-cp37-cp37m-linux_x86_64.whl
https://download.pytorch.org/whl/cu111/torchvision-0.10.1%2Bcu111-cp37-cp37m-linux_x86_64.whl
可能出现的问题:
```shell
1、module 'distutils' has no attribute 'version'
pip uninstall setuptools
pip install setuptools==59.5.0
2、ValueError: Error initializing torch.distributed using env:// rendezvous: environment variable RANK expected, but not set
之类的问题
在 train.py 的 if __name__ == '__main__':里面进行如下修改:
if __name__ == '__main__':
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
os.environ['RANK'] = '0'
os.environ['WORLD_SIZE'] = '1'
os.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = '5678'
main()
```

TFace运行流程记录