• 第P6周—好莱坞明星识别(1)


    一、 前期工作

    1. import torch
    2. import torch.nn as nn
    3. import torchvision.transforms as transforms
    4. import torchvision
    5. from torchvision import transforms,datasets
    6. import os ,PIL,pathlib,warnings
    7. warnings.filterwarnings("ignore")
    8. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    9. print(device)
    10. import os,PIL,random,pathlib
    11. data_dir = 'D:/P6/48-data/'
    12. data_dir = pathlib.Path(data_dir)
    13. data_path = list(data_dir.glob('*'))
    14. print (data_path)
    15. classname = [str(path).split("\\")[3] for path in data_path]
    16. print(classname)

    二、数据预处理 

    2.1 通过图片随机抽样计算 tansforms.Normalize()中红绿蓝通道均值和标准差(以下代码需在独立py文件中运行)

    将"D:/P6/48-data/"路径下子文件夹中所有图片复制到D:/all文件夹中

    1. import os
    2. import shutil
    3. # 主数据集根目录
    4. dataset_root = "D:/P6/48-data/"
    5. # 新文件夹的路径
    6. output_dir = "D:/all/"
    7. # 创建新文件夹(如果不存在)
    8. os.makedirs(output_dir, exist_ok=True)
    9. # 遍历主目录下的每个子文件夹
    10. for root, dirs, files in os.walk(dataset_root):
    11. for filename in files:
    12. if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp')): # 过滤出图片文件
    13. image_path = os.path.join(root, filename)
    14. output_path = os.path.join(output_dir, filename)
    15. # 复制图片文件到新文件夹
    16. shutil.copy2(image_path, output_path)
    17. print("图片已复制到新文件夹 'all' 中:", output_dir)

    对all文件夹中图片随机抽样并计算红绿蓝色道均值和标准差

    1. import os
    2. import random
    3. import cv2
    4. import numpy as np
    5. # 数据集根目录
    6. dataset_root = "D:/all/"
    7. # 采样比例
    8. sample_ratio = 0.1 # 10% 的采样率
    9. # 随机选择一部分图片进行采样
    10. all_image_paths = [os.path.join(dataset_root, filename) for filename in os.listdir(dataset_root)]
    11. sample_size = int(len(all_image_paths) * sample_ratio)
    12. sampled_image_paths = random.sample(all_image_paths, sample_size)
    13. # 初始化通道像素值总和和像素数量
    14. total_mean = np.zeros(3)
    15. total_std = np.zeros(3)
    16. total_pixels = 0
    17. # 遍历采样图片并计算通道的均值和标准差
    18. for image_path in sampled_image_paths:
    19. image = cv2.imread(image_path)
    20. image = image.astype(np.float32) / 255.0 # 归一化到 [0, 1]
    21. total_mean += image.mean(axis=(0, 1))
    22. total_std += image.std(axis=(0, 1))
    23. total_pixels += image.size // 3 # 3 通道的像素数量
    24. # 计算平均值和标准差
    25. dataset_mean = total_mean / len(sampled_image_paths)
    26. dataset_std = total_std / len(sampled_image_paths)
    27. print("均值:", dataset_mean)
    28. print("标准差:", dataset_std)

    2.2 样本标准化归一化处理

    1. train_transforms = transforms.Compose([
    2. transforms.Resize([224,224]),
    3. transforms.ToTensor(),
    4. transforms.Normalize(
    5. mean = [0.39354826, 0.41713402, 0.48036146],
    6. std = [0.25076334, 0.25809455, 0.28359835]
    7. )
    8. ])
    9. total_data = datasets.ImageFolder("D:/P6/48-data/", transform = train_transforms)
    10. print (total_data)

    在上述代码中,total_data = datasets.ImageFolder("D:/P6/48-data/", transform = train_transforms) 的作用是 对位于 "D:/P6/48-data/" 目录下的图像数据应用 train_transforms 中定义的数据进行转换。 目的是对训练数据进行预处理和数据增强,以提高深度学习模型的性能和泛化能力。

     2.3 将数据集中的类别(或标签)映射到相应的整数索引

    print(total_data.class_to_idx)

    三、划分数据集

    3.1 划分数据集

    1. train_size = int(0.8*len(total_data))
    2. test_size = len(total_data) - train_size
    3. train_dataset, test_dataset = torch.utils.data.random_split(total_data,[train_size, test_size])
    4. print(train_dataset,test_dataset)

    3.2 设置数据加载器

    1. batch_size = 32
    2. train_dl =torch.utils.data.DataLoader(train_dataset,
    3. batch_size = batch_size,
    4. shuffle = True,
    5. num_workers = 1)
    6. test_dl =torch.utils.data.DataLoader(test_dataset,
    7. batch_size = batch_size,
    8. shuffle = True,
    9. num_workers = 1)
    10. #当 shuffle=True 时:数据加载器会在每个训练周期之前对数据进行随机洗牌。
    11. # 这意味着每个周期都会以随机顺序提供数据样本,这有助于模型更好地学习数据的分布,
    12. # 减少模型对特定顺序的依赖。这通常是在训练深度学习模型时推荐的做法,
    13. # 特别是当数据集的样本顺序可能影响模型的训练效果时。

    四、调用VGG-16模型

    1. from torchvision.models import vgg16
    2. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    3. print("Using {} device\n".format(device))
    4. ''' 调用官方的VGG-16模型 '''
    5. # 加载预训练模型,并且对模型进行微调
    6. model = vgg16(pretrained = True).to(device) # 加载预训练的vgg16模型
    7. for param in model.parameters():
    8. param.requires_grad = False # 冻结模型的参数,这样子在训练的时候只训练最后一层的参数
    9. # 修改classifier模块的第6层(即:(6): Linear(in_features=4096, out_features=2, bias=True))
    10. # 注意查看我们下方打印出来的模型
    11. model.classifier._modules['6'] = nn.Linear(4096, 17) # 修改vgg16模型中最后一层全连接层,输出目标类别个数
    12. model.to(device)
    13. print(model)

     

  • 相关阅读:
    基于Java+Spring+Strusts2+Hibernate 社区智慧养老服务平台 系统设计与实现
    Linux
    什么是希尔排序?
    Python读取postgresql数据库
    【UML】软件工程中常用图:类图、部署图、时序图、状态图
    java 各种架构图汇总
    Spring的ioc的扫描器与bean的作用域与生命周期
    windows_tcp简单代码
    LeetCode 101. 对称二叉树
    【GridMask】《GridMask Data Augmentation》
  • 原文地址:https://blog.csdn.net/qq_60245590/article/details/133172891