练习 - 上传数据

已完成

现在,可以上传用于训练机器学习模型的图像了。 可通过两种方式上传图像:

  • 在自定义视觉门户中,选择“上传”,然后对图像进行标记。
  • 在 Jupyter Notebook 之类的工具中,使用自定义视觉 SDK 中包含的图像。

如果要上传大量数据、图像类和标记,则使用自定义视觉 SDK 会更快。 不过,你可以选择下面几节所述的选项之一。 完成这些步骤,以最适合你的方式在数据集中上传图像。

选项 1:使用自定义视觉门户上传和标记图像

必须通过每个子文件夹单独上传和标记图像。 对于本练习,可能需要仅上传四到五个子文件夹中的图像,具体取决于上传速度。 请记住,训练机器学习模块时,更多不同的示例将产生更好的结果。

  1. 在自定义视觉门户中创建项目:

    1. 转到 https://www.customvision.ai/projects 并登录。 选择“新建项目”。

    2. 在“创建新项目”中:

      1. 在“名称”中,输入所选的项目名称。

      2. 在“描述”中,输入模型的短描述。

      3. 在“资源组”中,选择在 Azure 门户中创建的资源组。

      4. 在“项目类型”中,选择“分类”。

      5. 在“分类类型”中,选择“多类(一个图像一个标记)”。

      6. 在“域”中,选择“常规”。

      7. 选择“创建项目”。

        显示如何在自定义视觉门户中创建新资源的屏幕截图。

    注意

    如果要导出模型以便在移动设备上、TensorFlow.js 中或 IoT 中部署,请在“域”下选择“精简”模型选项。 创建项目后,可以在设置中更改此选项。

  2. 为鸟类物种添加图像和标记:

    1. 在自定义视觉项目中,选择“添加图像”。

      自定义视觉项目中突出显示“添加图像”按钮的屏幕截图。

    2. 在“打开”中,转到从数据集 zip 文件中提取图像文件的 birds-photo 文件夹。

    3. 打开鸟类物种文件夹。

    4. 选择 Ctrl + A 来选择物种文件夹中的所有图像,然后选择“打开”。

      显示选择物种文件夹中所有图像的屏幕截图。

    5. 在“图像上传”中,在“我的标记”中添加说明以表明照片中显示的鸟类物种。

    6. 选择“上传 <数量> 个文件”。

      显示如何将标记说明添加到自定义视觉中已上传照片的屏幕截图。

  3. 重复上述步骤,将每个鸟类物种文件夹中的照片上传到下载的数据集。

选项 2:使用 Python 和自定义视觉 SDK 上传和标记图像

自定义视觉 SDK 可用于以下编程语言:Python、.NET、Node.js、Go 和 Java。 我们将使用 Python。 如果尚未安装 Python,建议通过安装 Anaconda 来获取它。 下载 Anaconda 时,即可获得 Python。

如果选择从 GitHub 下载代码,可以使用以下命令克隆存储库:

git clone https://github.com/MicrosoftDocs/mslearn-cv-classify-bird-species.git

按照以下步骤创建虚拟环境并将代码粘贴到该环境中:

  1. 打开所选的 IDE。 然后运行以下命令,导入包:

    !pip install azure-cognitiveservices-vision-customvision
    
  2. 导入运行脚本所需的包:

    from azure.cognitiveservices.vision.customvision.training import CustomVisionTrainingClient
    from azure.cognitiveservices.vision.customvision.training.models import ImageFileCreateEntry
    from azure.cognitiveservices.vision.customvision.training.models import ImageFileCreateBatch
    from msrest.authentication import ApiKeyCredentials 
    import numpy as np
    
  3. 现在,使用以下代码创建自定义视觉项目。 在运行代码之前,请将 <endpoint><key> 占位符替换为自定义视觉资源的值。

    获取自定义视觉资源值:

    1. Azure 门户中,转到自定义视觉资源。

    2. 在资源菜单的“资源管理”下,选择“键和终结点”。

    3. 从“终结点”框中复制值。 在代码中,将 <endpoint> 占位符替换为该值。

    4. 对于“键 1”,请选择复制图标以复制该键。 在代码中,将 <key> 占位符替换为该值。

      突出显示 Azure 门户中自定义视觉资源的终结点和键值的屏幕截图。

    代码将如以下示例所示:

    ENDPOINT = "<endpoint>"
    
    # Replace with a valid key
    training_key = "<key>"
    credentials = ApiKeyCredentials(in_headers={"Training-key": training_key})
    publish_iteration_name = "classifyBirdModel"
    
    trainer = CustomVisionTrainingClient(ENDPOINT, credentials)
    
    # Create a new project
    print ("Creating project...")
    project = trainer.create_project("Bird Classification")
    
    print("Project created!")
    
  4. 将下载的 bird-photos.zip 文件解压缩到保存了 Jupyter Notebook 文件的相同目录。 将以下要更改的代码添加到项目中的鸟类照片目录。

    # Change to the directory for the bird photos
    import os
    os.chdir('./bird-photos/custom-photos')
    

    警告

    仅运行此单元格中的代码一次。 如果尝试多次运行该单元格而不重新启动 Python 内核,则单元格运行将失败。

  5. 添加以下代码以获取鸟类标记的列表。 标记是基于 bird-photos/custom-photos 目录中的文件夹名称创建的:

    # Create a tag list from folders in bird directory
    tags = [name for name in os.listdir('.') if os.path.isdir(name)]
    print(tags)
    
  6. 接下来,我们将创建三个在 for 循环中调用的函数:

    • createTag 函数在自定义视觉项目中创建类标记。
    • createImageList 函数使用标记名称和标记 ID 生成图像列表。
    • image_list 函数从列表中成批上传图像。

    创建三个函数:

    1. 在 Jupyter Notebook 文件中,添加 createTag 函数代码。 此函数在自定义视觉项目中创建一个图像名称标记。

      tag_id = createTag(tag)
      print(f"tag creation done with tag id {tag_id}")
      image_list = createImageList(tag, tag_id)
      print("image_list created with length " + str(len(image_list)))
      
      # Break list into lists of 25 and upload in batches
      for i in range(0, len(image_list), 25):
          batch = ImageFileCreateBatch(images=image_list[i:i + 25])
          print(f'Upload started for batch {i} total items {len(image_list)} for tag {tag}...')
          uploadImageList(batch)
          print(f"Batch {i} Image upload completed. Total uploaded {len(image_list)} for tag {tag}")
      
    2. 接下来,添加 createImageList 函数代码。 该函数采用两个参数:文件夹名称列表中的 tag 名称,以及在自定义视觉项目中创建的标记的 tag_id。 该函数使用 base_image_url 值,将目录设置为包含我们根据文件夹名称创建的 tag 的图像的文件夹。 然后将每个图像附加到列表,我们将使用该列表批量上传到创建的 tag

      def createImageList(tag, tag_id):
      
      # Set directory to current tag.
         base_image_url = f"./{tag}/"
         photo_name_list = os.listdir(base_image_url)
         image_list = []
         for file_name in photo_name_list:
             with open(base_image_url+file_name, "rb") as image_contents:
                 image_list.append(ImageFileCreateEntry(name=base_image_url+file_name, contents=image_contents.read(), tag_ids=[tag_id]))
         return image_list
      
    3. 要添加的最后一个代码是创建 uploadImageList 函数。 我们传入从文件夹创建的 image_list,然后将该列表上传到 tag

      def uploadImageList(image_list):
            upload_result = trainer.create_images_from_files(project_id=project.id, batch=image_list)
            if not upload_result.is_batch_successful:
               print("Image batch upload failed.")
               for image in upload_result.images:
                    print("Image status: ", image.status)
               exit(-1)
      
  7. 现在,我们将为 main 方法添加代码。 对于每个标记,该方法都会调用创建的三个函数。 我们将循环遍历从 bird-photos/custom-photos 目录中的文件夹创建的 tags 集合中的每个标记(文件夹名称)。 下面是 for 循环包含的步骤:

    1. 调用前面创建的 createTag 函数在自定义视觉项目中创建 tag 类。

    2. 调用前面创建的 createImageList 函数,并使用自定义视觉返回的 tag 名称和 tag_id 值。 该函数返回要上传的图像列表。

    3. 调用前面创建的 imageList 函数以分批上传 image_list 中的图像(每批 25 张)。 我们将分批上传(每批 25 张),因为如果尝试同时上传整个数据集,自定义视觉将超时。

      for tag in tags: 
            tag_id = createTag(tag)
            print(f"tag creation done with tag id {tag_id}")
            image_list = createImageList(tag, tag_id)
            print("image_list created with length " + str(len(image_list)))
      
      # Break list into lists of 25 and upload in batches.
       for i in range(0, len(image_list), 25):
            batch = ImageFileCreateBatch(images=image_list[i:i + 25])
            print(f'Upload started for batch {i} total items {len  (image_list)} for tag {tag}...')
            uploadImageList(batch)
            print(f"Batch {i} Image upload completed. Total uploaded  {len(image_list)} for tag {tag}")
      

      警告

      仅运行此单元格中的代码一次。 如果尝试多次运行该单元格而不删除自定义视觉项目,则单元格运行将失败。