pytorch の高度な学習 (8): トレーニング済みのニューラル ネットワーク モデルを画像予測に使用する

コースのリソース: 

[小学生向け Pytorch] 9. モデルを使用して予測を行う (1)_哔哩哔哩_bilibili

 ノート:

Pytorch の高度な学習 (4): データ トレーニングに異なる分類モデルを使用する (alexnet、resnet、vgg など) - プログラマー募集


 目次

1.原理紹介

1. モデルとパラメーターをロードする

2.絵を読む

3. 画像の前処理

4.画像をテンソルに変換する

5. batch_size の次元を増やす

6. モデルの検証

6.1 モデルの予備出力

 6.2 予測値の確率が最も高い値と場所を出力する

 6.3 テンソルを numpy に変換する

6.4 予測カテゴリ

二、コード

1. 1 つの画像で予測を行う

2. フォルダーの全体像を予測する


        前のセクションでモデルをトレーニングした後、モデルは予測のために独自のデータをインポートします。このプロセスはトレーニング プロセスと似ています。プロジェクト ディレクトリは次のとおりで、pic は予測中に撮影した写真です。

1.原理紹介

1. モデルとパラメーターをロードする

モデル スケルトンは resnet18 を使用してトレーニングされ、トレーニング済みの重みファイル「model_resnet18_100.pth」を使用してパラメーターが読み込まれます。

# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

'''
    加载模型与参数
'''

# 加载模型
model = resnet18(pretrained=False, num_classes=5).to(device)  # 43.6%

# 加载模型参数
if device == "cpu":
    # 加载模型参数,权重文件传过来
    model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
    model.load_state_dict(torch.load("model_resnet18_100.pth"))

2.絵を読む

予測したいのは、sunflower1 の写真です。

img_path = './pic/sunflower1.jpg'

 

3. 画像の前処理

Image.open は画像を開き、RGB 形式に変換し、padding_black は画像を展開します。

img = Image.open(img_path)#打开图片
img = img.convert('RGB')#转换为RGB 格式
# 扩充
img = padding_black(img)

4.画像をテンソルに変換する

val_tf = transforms.Compose([
                transforms.Resize(224),
                transforms.ToTensor(),
                transform_BZ    # 标准化操作
            ])

# 图片转换为tensor
img_tensor = val_tf(img)

5. batch_size の次元を増やす

画像がモデルに直接渡されると、次のエラーが発生します。

 理由:

モデルは 4 次元入力を受け取りますが、画像の入力は 3 次元のみです. 必要な 4 次元入力の最初の次元は batch_size です. トレーニング済みモデルでは、batch_size=64 ですが、画像にはこの次元がありません、したがって、これを指定する必要があります。受信画像に別のチャネルを追加します。

  • dim=0 は、最初の次元の次元を増やすことを表します
# 增加batch_size维度
img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)

6. モデルの検証

6.1 モデルの予備出力

 モデルが出力された後、次の結果が表示されます. テンソルには 5 つの数値があります.

model.eval()
# 不进行梯度更新
with torch.no_grad():
    output_tensor = model(img_tensor)
    print(output_tensor)

 しかし、それらは必要な各クラスの確率値ではなく、0 から 1 の間ではないため、正規化にソフトマックスを使用する必要があります。正規化にはソフトマックスを使用します。

# 将输出通过softmax变为概率值
    output = torch.softmax(output_tensor,dim=1)
    print(output)

ソフトマックス操作が実行された後、結果が科学表記法を使用して表示され、5 つの数値の合計が 1 であることが わかります。

 6.2 予測値の確率が最も高い値と場所を出力する

# 输出可能性最大的那位
    pred_value, pred_index = torch.max(output, 1)
    print(pred_value)
    print(pred_index)

出力 出力確率は 1 で 100%、位置の添字は 3 で、4 番目のカテゴリであるひまわりカテゴリであることがわかります。

 6.3 テンソルを numpy に変換する

前のステップのデータ出力はテンソル形式であるため、最初に数値を numpy に変換してから、後続のラベル添え字をラベル クラスに変換する必要があります。

# 将数据从cuda转回cpu
pred_value = pred_value.detach().cpu().numpy()
pred_index = pred_index.detach().cpu().numpy()
    
print(pred_value)
print(pred_index)

結果を印刷すると、テンソル フラグなしで numpy クラスに正常に変換されていることがわかります。 

6.4 予測カテゴリ

テスト トレーニング セット ラベルの順序に対応している必要があるカテゴリの中国語リストを書き出します。

classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]

print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")

プリントアウトは、予測が正しく、精度が高いことを示しています。

二、コード

1. 1 つの画像で予測を行う

'''
    功能:按着路径,导入单张图片做预测
    作者: Leo在这

'''
from torchvision.models import resnet18
import torch
from PIL import Image
import torchvision.transforms as transforms
from torch.autograd import Variable

# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

'''
    加载模型与参数
'''

# 加载模型
model = resnet18(weights=False, num_classes=5).to(device)  # 43.6%

# 加载模型参数
if device == "cpu":
    # 加载模型参数,权重文件传过来
    model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
    model.load_state_dict(torch.load("model_resnet18_100.pth"))

'''
    加载图片与格式转化
'''
img_path = './pic/sunflower1.jpg'

'''
    图片进行预处理
'''
# 图片标准化
transform_BZ= transforms.Normalize(
    mean=[0.5, 0.5, 0.5],# 取决于数据集
    std=[0.5, 0.5, 0.5]
)

val_tf = transforms.Compose([
                transforms.Resize(224),
                transforms.ToTensor(),
                transform_BZ    # 标准化操作
            ])


def padding_black(img):  # 如果尺寸太小可以扩充
    w, h = img.size
    scale = 224. / max(w, h)
    img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
    size_fg = img_fg.size
    size_bg = 224
    img_bg = Image.new("RGB", (size_bg, size_bg))
    img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
                          (size_bg - size_fg[1]) // 2))
    img = img_bg
    return img

# 打开图片,转换为RGB

img = Image.open(img_path)#打开图片
img = img.convert('RGB')#转换为RGB 格式
# 扩充
img = padding_black(img)
# print(type(img))

# 图片转换为tensor
img_tensor = val_tf(img)
# print(type(img_tensor))

# 增加batch_size维度
img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)


'''
    数据输入与模型输出转换
'''
model.eval()
# 不进行梯度更新
with torch.no_grad():
    output_tensor = model(img_tensor)
    print(output_tensor)
    #
    # 将输出通过softmax变为概率值
    output = torch.softmax(output_tensor,dim=1)
    print(output)

    # 输出可能性最大的那位
    pred_value, pred_index = torch.max(output, 1)
    print(pred_value)
    print(pred_index)

    # 将数据从cuda转回cpu
    pred_value = pred_value.detach().cpu().numpy()
    pred_index = pred_index.detach().cpu().numpy()
    print(pred_value)
    print(pred_index)
    # #
    # 增加类别标签
    classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]
    print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")

2. フォルダーの全体像を予測する

ルート ディレクトリが pic であるフォルダーの画像予測を行うには、手順は単一の画像予測に似ており、for ループを使用してファイルをトラバースします。

'''
    功能:导入文件夹做预测
    作者:Leo在这
'''

from torchvision.models import resnet18
import torch
from PIL import Image
import torchvision.transforms as transforms
from torch.autograd import Variable

import os

# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

'''
    加载模型与参数
'''

# 加载模型
model = resnet18(pretrained=False, num_classes=5).to(device)  # 43.6%

if device == "cpu":
    # 加载模型参数
    model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
    model.load_state_dict(torch.load("model_resnet18_100.pth"))
'''
    加载图片与格式转化
'''

# 图片标准化
transform_BZ= transforms.Normalize(
    mean=[0.5, 0.5, 0.5],# 取决于数据集
    std=[0.5, 0.5, 0.5]
)

val_tf = transforms.Compose([##简单把图片压缩了变成Tensor模式
                transforms.Resize(224),
                transforms.ToTensor(),
                transform_BZ#标准化操作
            ])


def padding_black(img):  # 如果尺寸太小可以扩充
    w, h = img.size
    scale = 224. / max(w, h)
    img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
    size_fg = img_fg.size
    size_bg = 224
    img_bg = Image.new("RGB", (size_bg, size_bg))
    img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
                          (size_bg - size_fg[1]) // 2))
    img = img_bg
    return img


dir_loc = r"./pic"
model.eval()
with torch.no_grad():
    for a,b,c in os.walk(dir_loc):
        for filei in c:
            full_path = os.path.join(a,filei)
            # print(full_path)
            # img_path = './pic/sunflower3.jpg'

            img = Image.open(full_path)#打开图片
            img = img.convert('RGB')#转换为RGB 格式
            img = padding_black(img)
            # print(type(img))

            img_tensor = val_tf(img)
            # print(type(img_tensor))

            # 增加batch_size维度
            img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)


            '''
                数据输入与模型输出转换
            '''

            output_tensor = model(img_tensor)
            # 将输出通过softmax变为概率值
            output = torch.softmax(output_tensor,dim=1)

            # 输出可能性最大的那位
            pred_value, pred_index = torch.max(output, 1)

            pred_value = pred_value.detach().cpu().numpy()
            pred_index = pred_index.detach().cpu().numpy()

            # 增加类别标签
            classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]

            print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")

結果は次のようになります。

おすすめ

転載: blog.csdn.net/weixin_45662399/article/details/130146237