对以下代码结合实际写个详细的注释,阐述其中的原理?

这是个人脸表情识别的训练代码,databace_face是个存放了jpg文件的数据集,注释最好是行注释,因为好多库都不熟悉。


# k-means_opt.py
# -*- coding: utf-8 -*-
import shutil
import numpy as np
import torch
import torch.nn as nn
from torchvision import models, transforms
from PIL import Image
import os
from sklearn.cluster import KMeans


def predict(image, model):
    transform = transforms.Compose([
        transforms.Resize(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
    img = transform(image)
    img = torch.unsqueeze(img, 0)
    output = model(img)[0].data.numpy()
    return output


if __name__ == '__main__':
    class_names = 7
    model_path = 'model/weights.pth'
    # build model
    model_ft = models.resnet34(pretrained=False)
    num_ftrs = model_ft.fc.in_features
    model_ft.fc = nn.Sequential(
        nn.Dropout(0.5),
        nn.Linear(num_ftrs, 7),
        nn.Softmax(dim=1)
    )
    model_ft.load_state_dict(torch.load(model_path))
    img_path = 'database_face'
    img_list = os.listdir(img_path)
    model_ft.eval()
    list_a = []
    for value in img_list:
        try:
            image = Image.open(os.path.join(img_path, value))
            output = predict(image, model_ft)
            list_a.append(output)
        except:
            pass

    b = np.array(list_a)
    print(b)

    k = 7
    # 聚类
    kmodel = KMeans(n_clusters=k, init='k-means++', random_state=0)
    kmodel.fit(b)

    dir_path = os.listdir('database_face')
    for img_name in dir_path:
        try:
            image = Image.open('database_face/' + img_name)
            output = predict(image, model_ft)

            min_num = 9999
            min_index = 10
            for index, value in enumerate(kmodel.cluster_centers_):
                dis = np.linalg.norm(value - output)  # 欧氏距离,计算最近的点
                if dis < min_num:
                    min_num = dis
                    min_index = index
            shutil.copyfile('database_face/' + img_name, 'output/' + str(min_index) + '/' + img_name)
        except:
            pass

    # 训练完得到的7个中心点
    for index, value in enumerate(kmodel.cluster_centers_):
        print(value)

'

# k-means_opt.py
# -*- coding: utf-8 -*-
# shutil模块是对os模块的补充,主要针对文件的拷贝、删除、移动、压缩和解压操作
import shutil
# 用来存储和处理大型矩阵
import numpy as np
# 深度学习库
import torch
import torch.nn as nn
# torchvision由流行的数据集、模型架构和用于计算机视觉的常见图像转换组成
from torchvision import models, transforms
# 图像库
from PIL import Image
import os
# KMeans聚类算法
from sklearn.cluster import KMeans


# 定义预测函数,传入待预测图象及使用的模型
def predict(image, model):
    # 用Compose把多个步骤整合到一起
    # Resize用于调整图像尺寸,将原图像调整为224×224
    # ToTensor()将图像数据转换为tensor的
    # Normalize对图像进行标准化,mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225],是从imagenet训练集中抽样算出来的
    transform = transforms.Compose([
        transforms.Resize(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
    # 调用transform对图像进行处理
    img = transform(image)
    # torch.unsqueeze(input, dim, out=None)扩展维度,返回一个新的张量,对输入的既定位置插入维度1
    img = torch.unsqueeze(img, 0)
    # 调用模型,传入图像进行预测
    output = model(img)[0].data.numpy()
    return output


if __name__ == '__main__':
    # 应该是定义类别数为7,下文并未用到此变量
    class_names = 7
    # 定义要导入的训练好的模型路径
    model_path = 'model/weights.pth'
    # build model
    # 调用resnet34模型,不使用预训练
    model_ft = models.resnet34(pretrained=False)
    # 得到模型分类层个数,即原模型的分类类别数
    num_ftrs = model_ft.fc.in_features
    # 重写分类层参数,nn.Sequential一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行
    # nn.dropout是为了防止或减轻过拟合数值为不保留节点数的比例
    # nn.Linear重新定义输出层,将项目分类为7个类别
    # nn.Softmax分类层激活函数,dim用来指定哪一维度相加为1,具体参考http://www.zzvips.com/article/207118.html
    model_ft.fc = nn.Sequential(
        nn.Dropout(0.5),
        nn.Linear(num_ftrs, 7),
        nn.Softmax(dim=1)
    )
    # 从本地载入已经训练好的模型参数
    model_ft.load_state_dict(torch.load(model_path))
    # 定义图片路径
    img_path = 'database_face'
    # 得到该路径下的所有图片列表
    img_list = os.listdir(img_path)
    # 设置模型为评估模型,用于预测
    model_ft.eval()
    # 定义用于存储预测结果的列表
    list_a = []
    # 循环调用图片列表中的每一张图片
    for value in img_list:
        try:
            # 读取本地图片到内存中
            image = Image.open(os.path.join(img_path, value))
            # 调用模型对图片进行预测
            output = predict(image, model_ft)
            # 将预测结果添加到列表中
            list_a.append(output)
        except:
            pass
    # 将列表转换为数组并打印出来
    b = np.array(list_a)
    print(b)
    # 定义簇的个数为7
    k = 7
    # 聚类
    # 调用KMeans聚类模型,聚类簇个数为7
    kmodel = KMeans(n_clusters=k, init='k-means++', random_state=0)
    # 使用聚类模型对预测结果进行聚类
    kmodel.fit(b)

    dir_path = os.listdir('database_face')
    for img_name in dir_path:
        try:
            image = Image.open('database_face/' + img_name)
            output = predict(image, model_ft)

            min_num = 9999
            min_index = 10
            # 循环读取聚类中心的下标及值
            for index, value in enumerate(kmodel.cluster_centers_):
                dis = np.linalg.norm(value - output)  # 欧氏距离,计算最近的点
                # 判断距离是否为最小距离
                if dis < min_num:
                    # 定义最小距离为当前距离,下标为当前下标
                    min_num = dis
                    min_index = index
            # 将database_face中的图片复制到output/str(min_index)文件夹下
            shutil.copyfile('database_face/' + img_name, 'output/' + str(min_index) + '/' + img_name)
        except:
            pass

    # 训练完得到的7个中心点,打印值
    for index, value in enumerate(kmodel.cluster_centers_):
        print(value)

如果有帮助的话望采纳,谢谢


 
# k-means_opt.py
# -*- coding: utf-8 -*-
import shutil#操作文件的库
import numpy as np#支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
import torch#torch基础库
import torch.nn as nn#torch神经网络库
from torchvision import models, transforms# torchvision 是 pytorch下图像处理包,做一些图像预处理(torchvision.transforms),导入预训练模型(torchvision.models)
from PIL import Image#对图像处理的包
import os#在python环境下对文件,文件夹执行操作的一个模块
from sklearn.cluster import KMeans#导入kmeans库
 
 
def predict(image, model):#定义函数
    transform = transforms.Compose([#Compose()类。这个类的主要作用是串联多个图片变换的操作。
        transforms.Resize(224),#设置大小
        transforms.ToTensor(),#将shape为(H, W, C)的nump.ndarray或img转为shape为(C, H, W)的tensor,其将每一个数值归一化到[0,1]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])#Normalize是把图像数据从 [0,1]变成 [-1,1],
    img = transform(image)#生成一张变换后的新图片
    img = torch.unsqueeze(img, 0)#对数据的维度进行压缩,去掉维数为1的的维度
    output = model(img)[0].data.numpy()#.numpy()把tensor变成numpy
    return output#返回
 
 
if __name__ == '__main__':
    class_names = 7#7类
    model_path = 'model/weights.pth'#模型路径
    # build model
    model_ft = models.resnet34(pretrained=False)#如果你需要用预训练模型,设置pretrained=True 如果你不需要用预训练模型,设置pretrained=False
    num_ftrs = model_ft.fc.in_features#最后一个全连接的输入维度
    model_ft.fc = nn.Sequential(
        nn.Dropout(0.5),#0.5 是指该层(layer)的神经元在每次迭代训练时会随机有 50% 的可能性被丢弃(失活),不参与训练,
        nn.Linear(num_ftrs, 7),#设置网络中的全连接层的in_features和out_features
        nn.Softmax(dim=1)#将Softmax函数应用于一个n维输入张量,对其进行缩放,使n维输出张量的元素位于[0,1]范围内,总和为1 当dim=1时,指的是在维度1上的元素相加等于1
    )
    model_ft.load_state_dict(torch.load(model_path))#将预训练的参数权重加载到新的模型之中
    img_path = 'database_face'#图的路径
    img_list = os.listdir(img_path)#返回指定的文件夹包含的文件或文件夹的名字的列表。
    model_ft.eval()#不启用 BatchNormalization 和 Dropout,将BatchNormalization和Dropout置为False
    list_a = []#空列表
    for value in img_list:#在图像列表里遍历
        try:
            image = Image.open(os.path.join(img_path, value))#打开图像
            output = predict(image, model_ft)#输出预测结果
            list_a.append(output)#加入列表
        except:#如果无文件跳过
            pass
 
    b = np.array(list_a)#创建为numpy类型
    print(b)#输出
 
    k = 7
    # 聚类
    kmodel = KMeans(n_clusters=k, init='k-means++', random_state=0)#kmeans聚类
    kmodel.fit(b)
 
    dir_path = os.listdir('database_face')#知道文件列表
    for img_name in dir_path:#循环遍历
        try:
            image = Image.open('database_face/' + img_name)#打开文件
            output = predict(image, model_ft)#预测
 
            min_num = 9999#最小数
            min_index = 10#最小下标
            for index, value in enumerate(kmodel.cluster_centers_):
                dis = np.linalg.norm(value - output)  # 欧氏距离,计算最近的点
                if dis < min_num:#小于最小值
                    min_num = dis#更新值
                    min_index = index#更新下标
            shutil.copyfile('database_face/' + img_name, 'output/' + str(min_index) + '/' + img_name)#复制文件
        except:
            pass
 
    # 训练完得到的7个中心点
    for index, value in enumerate(kmodel.cluster_centers_):
        print(value)