# 轻松学Pytorch – 年龄与性别预测

• 如何实现卷积神经网络的多任务不同输出
• 如何同时实现分类跟回归预测
• 基于人脸年龄与性别的公开数据的数据制作
• 使用多任务网络实现推理预测

`https://susanqq.github.io/UTKFace/`

[age]_[gender]_[race]_[date&time].jpg

• Age表示年龄，范围在0~116岁之间
• Gender表示性别，0表示男性，1表示女性
• Race表示人种，

```class AgeGenderDataset(Dataset):
def __init__(self, root_dir):
self.transform = transforms.Compose([transforms.ToTensor()])
img_files = os.listdir(root_dir)
nums_ = len(img_files)
# age: 0 ~116, 0 :male, 1 :female
self.ages = []
self.genders = []
self.images = []
index = 0
for file_name in img_files:
age_gender_group = file_name.split("_")
age_ = age_gender_group[0]
gender_ = age_gender_group[1]
self.genders.append(np.float32(gender_))
self.ages.append(np.float32(age_)/max_age)
self.images.append(os.path.join(root_dir, file_name))
index += 1

def __len__(self):
return len(self.images)

def num_of_samples(self):
return len(self.images)

def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
image_path = self.images[idx]
else:
image_path = self.images[idx]
img = cv.imread(image_path)  # BGR order
h, w, c = img.shape
# rescale
img = cv.resize(img, (64, 64))
img = (np.float32(img) /255.0 - 0.5) / 0.5
# H, W C to C, H, W
img = img.transpose((2, 0, 1))
sample = {'image': torch.from_numpy(img), 'age': self.ages[idx], 'gender': self.genders[idx]}
return sample```

```MyMulitpleTaskNet(
(cnn_layers): Sequential(
(0): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU()
(2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(4): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(5): ReLU()
(6): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(8): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): ReLU()
(10): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(11): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(12): Conv2d(96, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU()
(14): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(15): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(16): Conv2d(128, 196, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(17): ReLU()
(18): BatchNorm2d(196, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(19): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(age_fc_layers): Sequential(
(0): Linear(in_features=196, out_features=25, bias=True)
(1): ReLU()
(2): Linear(in_features=25, out_features=1, bias=True)
(3): Sigmoid()
)
(gender_fc_layers): Sequential(
(0): Linear(in_features=196, out_features=25, bias=True)
(1): ReLU()
(2): Linear(in_features=25, out_features=2, bias=True)
)
)```

```if train_on_gpu:
model.cuda()

ds = AgeGenderDataset("D:/python/pytorch_tutorial/UTKFace/")
num_train_samples = ds.num_of_samples()
bs = 16

# 训练模型的次数
num_epochs = 25
# optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
model.train()

# 损失函数
mse_loss = torch.nn.MSELoss()
cross_loss = torch.nn.CrossEntropyLoss()
index = 0
for epoch in  range(num_epochs):
train_loss = 0.0
for i_batch, sample_batched in enumerate(dataloader):
images_batch, age_batch, gender_batch = \
sample_batched['image'], sample_batched['age'], sample_batched['gender']
if train_on_gpu:
images_batch, age_batch, gender_batch = images_batch.cuda(), age_batch.cuda(), gender_batch.cuda()

# forward pass: compute predicted outputs by passing inputs to the model
m_age_out_, m_gender_out_ = model(images_batch)
age_batch = age_batch.view(-1, 1)
gender_batch = gender_batch.long()

# calculate the batch loss
loss = mse_loss(m_age_out_, age_batch) + cross_loss(m_gender_out_, gender_batch)

# backward pass: compute gradient of the loss with respect to model parameters
loss.backward()

# perform a single optimization step (parameter update)
optimizer.step()

# update training loss
train_loss += loss.item()
if index % 100 == 0:
print('step: {} \tTraining Loss: {:.6f} '.format(index, loss.item()))
index += 1

# 计算平均损失
train_loss = train_loss / num_train_samples

# 显示训练集与验证集的损失函数
print('Epoch: {} \tTraining Loss: {:.6f} '.format(epoch, train_loss))

# save model
model.eval()
torch.save(model, 'age_gender_model.pt')```

``` 1def video_landmark_demo():
2    cnn_model = torch.load("./age_gender_model.pt")
3    print(cnn_model)
4    # capture = cv.VideoCapture(0)
5    capture = cv.VideoCapture("D:/images/video/example_dsh.mp4")
6
7    # load tensorflow model
8    net = cv.dnn.readNetFromTensorflow(model_bin, config=config_text)
9    while True:
10        ret, frame = capture.read()
11        if ret is not True:
12            break
13        frame = cv.flip(frame, 1)
14        h, w, c = frame.shape
15        blobImage = cv.dnn.blobFromImage(frame, 1.0, (300, 300), (104.0, 177.0, 123.0), False, False);
16        net.setInput(blobImage)
17        cvOut = net.forward()
18        # 绘制检测矩形
19        for detection in cvOut[0,0,:,:]:
20            score = float(detection[2])
21            if score > 0.5:
22                left = detection[3]*w
23                top = detection[4]*h
24                right = detection[5]*w
25                bottom = detection[6]*h
26
27                # roi and detect landmark
28                roi = frame[np.int32(top):np.int32(bottom),np.int32(left):np.int32(right),:]
29                rw = right - left
30                rh = bottom - top
31                img = cv.resize(roi, (64, 64))
32                img = (np.float32(img) / 255.0 - 0.5) / 0.5
33                img = img.transpose((2, 0, 1))
34                x_input = torch.from_numpy(img).view(1, 3, 64, 64)
35                age_, gender_ = cnn_model(x_input.cuda())
36                predict_gender = torch.max(gender_, 1)[1].cpu().detach().numpy()[0]
37                gender = "Male"
38                if predict_gender == 1:
39                    gender = "Female"
40                predict_age = age_.cpu().detach().numpy()*116.0
41                print(predict_gender, predict_age)
42
43                # 绘制
44                cv.putText(frame, ("gender: %s, age:%d"%(gender, int(predict_age[0][0]))), (int(left), int(top)-15), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 1)
45                cv.rectangle(frame, (int(left), int(top)), (int(right), int(bottom)), (255, 0, 0), thickness=2)
46                # cv.putText(frame, "score:%.2f"%score, (int(left), int(top)), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
47                c = cv.waitKey(10)
48                if c == 27:
49                    break
50                cv.imshow("face detection + landmark", frame)
51
52    cv.waitKey(0)
53    cv.destroyAllWindows()
54
55
56if __name__ == "__main__":
57    video_landmark_demo()```

0 条评论

• ### 深度学习AI美颜系列----AI美发算法(美妆相机/天天P图染发特效)

给照片或者视频中的人物头发换颜色，这个技术已经在手机app诸如天天P图，美图秀秀等应用中使用，并获得了不少用户的青睐。如何给照片或者视频中的人物头发换发色？换发...

• ### Windows下TensorFlow安装与代码测试

Windows下TensorFlow安装与代码测试 一：Tensorflow介绍 TensorFlow是谷歌的深度学习应用开发框架，其思想基于数据流图与节点图实...

• ### #Python3中字符串的比较

20.字符串的比较 从第一个字符开始比较谁的ASCII值谁就大 如果前面相同 则比较后一位直到比较出谁大 如果都相同 则相等

• ### 全局变量的三种声明方法

显示true FWK未定义，说明隐式声明的全局变量可以被delete，与global对象的parseInt、escape、parseFloat等等类似，可直接被...

• ### The `useMongoClient` option is no longer necessary in mongoose 5.x, please remove it.

mongoose升级到5.X版本就不支持useMongoClient 这种写法了，而是应该写成useNewUrlParser。

• ### 【SPA大赛】菜鸟在数据挖掘中的体验

本文从四个方面分享了参加腾讯社交广告比赛的一些想法以及从中吸取的经验和教训。

• ### 【Python3】f-string——s

f-string，亦称为格式化字符串常量（formatted string literals），是Python3.6新引入的一种字符串格式化方法，主要...

• ### 3.1 Contour绘制

首先一起学习利用百度的开源项目绘制contour，百度搜索“echarts heatmap”，找到热力图的一个案例（http://echarts.baidu.c...

• ### 【必读】腾讯企点销售智推上手指南

? 企点营销-销售智推 社交场景的销售客户管理工具 筛选消费者需要的精准信息及内容为销售赋能 01 使用前授权准备 ①开通小程序 企业必须申请一个已认证的小...

### OpenCV学堂

OpenCV开发专家计算机视觉开发