深度学习图像分类精度
by Anne Bonner
通过安妮·邦纳
如何以高于97%的精度构建图像分类器 (How to build an image classifier with greater than 97% accuracy)
清晰完整的成功蓝图 (A clear and complete blueprint for success)
How do you teach a computer to look at an image and correctly identify it as a flower? How do you teach a computer to see an image of a flower and then tell you exactly what species of flower it is when even you don’t know what species it is?
您如何教计算机查看图像并将其正确识别为花朵? 您如何教计算机查看花朵的图像,然后甚至在您不知道花朵是什么种类的情况下,也能准确告诉您花朵是什么种类的呢?
Let me show you!
让我给你演示!
This article will take you through the basics of creating an image classifier with PyTorch. You can imagine using something like this in a phone app that tells you the name of the flower your camera is looking at. You could, if you wanted, train this classifier and then export it for use in an application of your own.
本文将带您了解使用PyTorch创建图像分类器的基础知识。 您可以想象在电话应用程序中使用类似这样的内容,告诉您相机正在看的花朵的名称。 如果需要,您可以训练此分类器,然后将其导出以在自己的应用程序中使用。
What you do from here depends entirely on you and your imagination.
您在这里所做的一切完全取决于您和您的想象力。
I put this article together for anyone out there who’s brand new to all of this and looking for a place to begin. It’s up to you to take this information, improve on it, and make it your own!
我将本文汇总给所有对此不熟悉的人,并寻找一个开始的地方。 您可以自行获取这些信息,对其进行改进并自行创建!
If you want to view the notebook, you can find it here.
Because this PyTorch image classifier was built as a final project for a Udacity program, the code draws on code from Udacity which, in turn, draws on the official PyTorch documentation. Udacity also provided a JSON file for label mapping. That file can be found in this GitHub repo.
由于此PyTorch图像分类器是作为Udacity程序的最终项目构建的,因此该代码借鉴了Udacity的代码,而Udacity则借鉴了PyTorch官方文档。 Udacity还提供了一个用于标签映射的JSON文件。 该文件可以在该GitHub存储库中找到 。
Information about the flower data set can be found here. The data set includes a separate folder for each of the 102 flower classes. Each flower is labeled as a number and each of the numbered directories holds a number of .jpg files.
可以在此处找到有关花朵数据集的信息。 数据集为102个花朵类别的每一个都包含一个单独的文件夹。 每朵花都标记为一个数字,每个编号的目录都包含许多.jpg文件。
让我们开始吧! (Let’s get started!)
Because this is a neural network using a larger dataset than my CPU could handle in any reasonable amount of time, I went ahead and set up my image classifier in Google Colab. Colab is truly awesome because it provides free GPU. (If you’re new to Colab, check out this article on getting started with Google Colab!)
由于这是一个神经网络,使用的数据集超出了我的CPU在任何合理的时间内所能处理的数据量,因此我继续在Google Colab中设置了图像分类器 。 Colab确实很棒,因为它提供了免费的GPU 。 (如果您是Colab的新手, 请查看有关Google Colab入门的本文 !)
Because I was using Colab, I needed to start by importing PyTorch. You don’t need to do this if you aren’t using Colab.
因为我使用的是Colab,所以我需要先导入PyTorch。 如果您不使用Colab,则无需执行此操作。
*** UPDATE! (01/29)*** Colab now supports native PyTorch!!! You shouldn’t need to run the code below, but I’m leaving it up just in case anyone is having any issues!
***更新! (01/29)*** Colab现在支持本机PyTorch !!! 您不需要运行下面的代码,但为了防止任何人遇到任何问题,我将其保留下来!
# Import PyTorch if using Google Colab# http://pytorch.org/from os.path import existsfrom wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tagplatform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())cuda_output = !ldconfig -p|grep cudart.so|sed -e 's/.*\.\([0-9]*\)\.\([0-9]*\)$/cu\1\2/'accelerator = cuda_output[0] if exists('/dev/nvidia0') else 'cpu'
!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvisionimport torch
Then, after having some trouble with Pillow (it’s buggy in Colab!), I just went ahead and ran this:
然后,在使用Pillow遇到麻烦(在Colab中是越野车!)之后,我继续进行以下操作:
import PILprint(PIL.PILLOW_VERSION)
If you get anything below 5.3.0, use the dropdown menu under “Runtime” to “Restart runtime” and run this cell again. You should be good to go!
如果低于5.3.0,请使用“运行时”下的下拉菜单“重新启动运行时”,然后再次运行此单元格。 你应该很好走!
You’ll want to be using GPU for this project, which is incredibly simple to set up on Colab. You just go to the “runtime” dropdown menu, select “change runtime type” and then select “GPU” in the hardware accelerator drop-down menu!
您将要为此项目使用GPU,在Colab上进行设置非常简单。 您只需转到“运行时”下拉菜单,选择“更改运行时类型”,然后在硬件加速器下拉菜单中选择“ GPU”!
Then I like to run
那我喜欢跑步
train_on_gpu = torch.cuda.is_available()
if not train_on_gpu: print('Bummer! Training on CPU ...')else: print('You are good to go! Training on GPU ...')
just to make sure it’s working. Then run
只是为了确保它能正常工作。 然后跑
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
to define the device.
定义设备。
After this, import the files. There are a ton of ways to do this, including mounting your Google Drive if you have your dataset stored there, which is actually really simple. Even though I didn’t wind up finding that to be the most useful solution, I’m including that below, just because it’s so easy and useful.
之后,导入文件。 有很多方法可以做到这一点,包括在存储有数据集的情况下挂载Google云端硬盘,这实际上非常简单。 即使我没有发现这是最有用的解决方案,但我还是将其包含在下面,只是因为它是如此简单和有用。
from google.colab import drivedrive.mount('/content/gdrive')
Then you’ll see a link, click on that, allow access, copy the code that pops up, paste it in the box, hit enter, and you’re good to go! If you don’t see your drive in the side box on the left, just hit “refresh” and it should show up.
然后,您将看到一个链接,单击该链接,允许访问,复制弹出的代码,将其粘贴到框中,然后按Enter,您就可以开始了! 如果您在左侧边栏中没有看到驱动器,只需单击“刷新”,它就会显示出来。
(Run the cell, click the link, copy the code on the page, paste it in the box, hit enter, and you’ll see this when you’ve successfully mounted your drive):
(运行单元格,单击链接,将代码复制到页面上,将其粘贴到框中,按回车键,成功安装驱动器后,您会看到此信息):
It’s actually super easy!
实际上,这非常容易!
However, if you’d rather download a shared zip file link (this wound up being easier and faster for this project), you can use:
但是,如果您希望下载共享的zip文件链接(此项目在此项目中变得越来越容易和快捷),则可以使用:
!wget !unzip
For example:
例如:
!wget -cq https://s3.amazonaws.com/content.udacity-data.com/courses/nd188/flower_data.zip!unzip -qq flower_data.zip
That will give you Udacity’s flower data set in seconds!
这样一来,您就可以在几秒钟内获得Udacity的花朵数据集!
(If you’re uploading small files, you can just upload them directly with some simple code. However, if you want to, you can also just go to the left side of the screen and click “upload files” if you don’t feel like running some simple code to grab a local file.)
(如果要上传小文件,则可以使用一些简单的代码直接将其上传。但是,如果需要,您也可以转到屏幕左侧,然后点击“上传文件”就像运行一些简单的代码来获取本地文件一样。)
After loading the data, I imported the libraries I wanted to use:
加载数据后,我导入了要使用的库:
%matplotlib inline%config InlineBackend.figure_format = 'retina'
import timeimport jsonimport copy
import matplotlib.pyplot as pltimport seaborn as snsimport numpy as npimport PIL
from PIL import Imagefrom collections import OrderedDict
import torchfrom torch import nn, optimfrom torch.optim import lr_schedulerfrom torch.autograd import Variableimport torchvisionfrom torchvision import datasets, models, transformsfrom torch.utils.data.sampler import SubsetRandomSamplerimport torch.nn as nnimport torch.nn.functional as F
Next comes the data transformations! You want to make sure to use several different types of transformations on your training set in order to help your program learn as much as it can. You can create a more robust model by training it on flipped, rotated, and cropped images.
接下来是数据转换! 您想确保对训练集使用几种不同类型的转换,以帮助您的程序尽可能多地学习。 您可以通过对翻转,旋转和裁剪的图像进行训练来创建更强大的模型。
The means that standard deviations are provided to normalize the image values before passing them to our network, but they can also be found by looking at the mean and standard deviation values of the different dimensions of the image tensors. The official documentation is incredibly helpful here!
提供标准偏差是为了在将图像值传递到我们的网络之前对其进行归一化,但是也可以通过查看图像张量不同维度的平均值和标准偏差值来找到它们。 官方文档在这里非常有用!
For my image classifier, I kept it simple with:
对于我的图像分类器,我简化了它:
data_transforms = { 'train': transforms.Compose([ transforms.RandomRotation(30), transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), 'valid': transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ])}
# Load the datasets with ImageFolderimage_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'valid']}
# Using the image datasets and the trainforms, define the dataloadersbatch_size = 64dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True, num_workers=4) for x in ['train', 'valid']}
class_names = image_datasets['train'].classes
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'valid']}class_names = image_datasets['train'].classes
As you can see above, I also defined the batch size, data loaders, and class names in the code above.
如您在上面看到的,我还在上面的代码中定义了批处理大小,数据加载器和类名。
To take a very quick look at the data and check my device, I ran:
为了快速查看数据并检查我的设备,我运行了:
print(dataset_sizes)print(device)
{'train': 6552, 'valid': 818}cuda:0
Next, we need to do some mapping from the label number and the actual flower name. Udacity provided a JSON file for this mapping to be done simply.
接下来,我们需要从标签编号和实际花名进行一些映射。 Udacity提供了一个JSON文件来简化此映射。
with open('cat_to_name.json', 'r') as f: cat_to_name = json.load(f)
In order to test the data loader, run:
为了测试数据加载器,请运行:
images, labels = next(iter(dataloaders['train']))rand_idx = np.random.randint(len(images))# Print(rand_idx)print("label: {}, class: {}, name: {}".format(labels[rand_idx].item(), class_names[labels[rand_idx].item()], cat_to_name[class_names[labels[rand_idx].item()]]))
Now it starts to get even more exciting! A number of models in the last several years have been created by people far, far more qualified than most of us for reuse in computer vision problems. PyTorch makes it easy to load pre-trained models and build on them, which is exactly what we’re going to do for this project. The choice of model is entirely up to you!
现在,它开始变得更加令人兴奋! 在过去的几年中,人们创造了许多模型,这些模型远比我们大多数人具有重用计算机视觉问题的资格。 PyTorch使得加载预训练的模型并在其上构建变得容易 ,而这正是我们为该项目要做的。 型号的选择完全取决于您!
Some of the most popular pre-trained models, like ResNet, AlexNet, and VGG, come from the ImageNet Challenge. These pre-trained models allow others to quickly obtain cutting-edge results in computer vision without needing such large amounts of computer power, patience, and time. I actually had great results with DenseNet and decided to use DenseNet161, which gave me very good results relatively quickly.
一些最受欢迎的预训练模型,例如ResNet,AlexNet和VGG,都来自ImageNet挑战赛。 这些经过预训练的模型使其他人可以快速获得最新的计算机视觉结果,而无需大量的计算机功能,耐心和时间。 实际上,我在DenseNet上取得了不错的成绩,因此决定使用DenseNet161,这样相对较快地给了我很好的效果。
You can quickly set this up by running
您可以通过运行以下命令快速进行设置
model = models.densenet161(pretrained=True)
but it might be more interesting to give yourself a choice of model, optimizer, and scheduler. In order to set up a choice in architecture, run
但是让自己选择模型,优化器和调度器可能会更有趣。 为了设置体系结构中的选择,请运行
model_name = 'densenet' #vggif model_name == 'densenet': model = models.densenet161(pretrained=True) num_in_features = 2208 print(model)elif model_name == 'vgg': model = models.vgg19(pretrained=True) num_in_features = 25088 print(model.classifier)else: print("Unknown model, please choose 'densenet' or 'vgg'")
which allows you to quickly set up an alternate model.
这使您可以快速设置备用模型。
After that, you can start to build your classifier, using the parameters that work best for you. I went ahead and built
之后,您可以使用最适合您的参数开始构建分类器。 我继续建造
for param in model.parameters(): param.requires_grad = False
def build_classifier(num_in_features, hidden_layers, num_out_features): classifier = nn.Sequential() if hidden_layers == None: classifier.add_module('fc0', nn.Linear(num_in_features, 102)) else: layer_sizes = zip(hidden_layers[:-1], hidden_layers[1:]) classifier.add_module('fc0', nn.Linear(num_in_features, hidden_layers[0])) classifier.add_module('relu0', nn.ReLU()) classifier.add_module('drop0', nn.Dropout(.6)) classifier.add_module('relu1', nn.ReLU()) classifier.add_module('drop1', nn.Dropout(.5)) for i, (h1, h2) in enumerate(layer_sizes): classifier.add_module('fc'+str(i+1), nn.Linear(h1, h2)) classifier.add_module('relu'+str(i+1), nn.ReLU()) classifier.add_module('drop'+str(i+1), nn.Dropout(.5)) classifier.add_module('output', nn.Linear(hidden_layers[-1], num_out_features)) return classifier
which allows for an easy way to change the number of hidden layers that I’m using, as well as quickly adjusting the dropout rate. You may decide to add additional ReLU and dropout layers in order to more finely hone your model.
这提供了一种简单的方法来更改我正在使用的隐藏层的数量以及快速调整辍学率。 您可以决定添加其他ReLU和辍学图层,以便更精细地磨练模型。
Next, work on training your classifier parameters. I decided to make sure I only trained the classifier parameters here while having feature parameters frozen. You can get as creative as you want with your optimizer, criterion, and scheduler. The criterion is the method used to evaluate the model fit, the optimizer is the optimization method used to update the weights, and the scheduler provides different methods for adjusting the learning rate and step size used during optimization.
接下来,训练分类器参数。 我决定确保只在冻结特征参数的同时在这里训练分类器参数。 使用优化器,条件和调度程序,您可以根据需要获得创意。 标准是用于评估模型拟合的方法,优化器是用于更新权重的优化方法,调度器提供了不同的方法来调整优化过程中使用的学习率和步长。
Try as many options and combinations as you can to see what gives you the best result. You can see all of the official documentation here. I recommend taking a look at it and making your own decisions about what you want to use. You don’t literally have an infinite number of options here, but it sure feels like it once you start playing around!
尝试尽可能多的选项和组合,以查看能带来最佳效果的方法。 您可以在此处查看所有官方文档。 我建议您看一下它,并对您要使用的东西做出自己的决定。 您实际上在这里没有无限多个选项,但是一旦您开始玩耍,肯定会感觉像是!
hidden_layers = None
classifier = build_classifier(num_in_features, hidden_layers, 102)print(classifier)
# Only train the classifier parameters, feature parameters are frozenif model_name == 'densenet': model.classifier = classifier criterion = nn.CrossEntropyLoss() optimizer = optim.Adadelta(model.parameters()) sched = optim.lr_scheduler.StepLR(optimizer, step_size=4)elif model_name == 'vgg': model.classifier = classifier criterion = nn.NLLLoss() optimizer = optim.Adam(model.classifier.parameters(), lr=0.0001) sched = lr_scheduler.StepLR(optimizer, step_size=4, gamma=0.1)else: pass
Now it’s time to train your model.
现在是时候训练您的模型了。
# Adapted from https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html
def train_model(model, criterion, optimizer, sched, num_epochs=5): since = time.time()
best_model_wts = copy.deepcopy(model.state_dict()) best_acc = 0.0
for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch+1, num_epochs)) print('-' * 10)
# Each epoch has a training and validation phase for phase in ['train', 'valid']: if phase == 'train': model.train() # Set model to training mode else: model.eval() # Set model to evaluate mode
running_loss = 0.0 running_corrects = 0
# Iterate over data. for inputs, labels in dataloaders[phase]: inputs = inputs.to(device) labels = labels.to(device)
# Zero the parameter gradients optimizer.zero_grad()
# Forward # track history if only in train with torch.set_grad_enabled(phase == 'train'): outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels)
# Backward + optimize only if in training phase if phase == 'train': #sched.step() loss.backward() optimizer.step()
# Statistics running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data)
epoch_loss = running_loss / dataset_sizes[phase] epoch_acc = running_corrects.double() / dataset_sizes[phase]
print('{} Loss: {:.4f} Acc: {:.4f}'.format( phase, epoch_loss, epoch_acc))
# Deep copy the model if phase == 'valid' and epoch_acc > best_acc: best_acc = epoch_acc best_model_wts = copy.deepcopy(model.state_dict())
print()
time_elapsed = time.time() - since print('Training complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) print('Best val Acc: {:4f}'.format(best_acc))
# Load best model weights model.load_state_dict(best_model_wts) return model
epochs = 30model.to(device)model = train_model(model, criterion, optimizer, sched, epochs)
I wanted to be able to monitor my epochs easily and also keep track of the time elapsed as my model was running. The code above includes both, and the results are pretty good! You can see that the model is quickly learning and the accuracy on the validation set quickly reached over 95% by epoch 7!
我希望能够轻松监视自己的时期,并跟踪模型运行时所经过的时间。 上面的代码同时包含了两者,结果非常好! 您可以看到该模型正在快速学习,并且到第7个时辰,验证集的准确性Swift达到了95%以上!
Epoch 1/30----------train Loss: 2.4793 Acc: 0.4791valid Loss: 0.9688 Acc: 0.8191Epoch 2/30----------train Loss: 0.8288 Acc: 0.8378valid Loss: 0.4714 Acc: 0.9010Epoch 3/30----------train Loss: 0.5191 Acc: 0.8890valid Loss: 0.3197 Acc: 0.9181Epoch 4/30----------train Loss: 0.4064 Acc: 0.9095valid Loss: 0.2975 Acc: 0.9169Epoch 5/30----------train Loss: 0.3401 Acc: 0.9214valid Loss: 0.2486 Acc: 0.9401Epoch 6/30----------train Loss: 0.3111 Acc: 0.9303valid Loss: 0.2153 Acc: 0.9487Epoch 7/30----------train Loss: 0.2987 Acc: 0.9298valid Loss: 0.1969 Acc: 0.9584
...
Training complete in 67m 43sBest val Acc: 0.973105
You can see that running this code on Google Colab with GPU took just over an hour.
您会看到,使用GPU在Google Colab上运行此代码仅花了一个多小时。
Now it’s time for evaluation
现在该进行评估了
model.eval()
accuracy = 0
for inputs, labels in dataloaders['valid']: inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) # Class with the highest probability is our predicted class equality = (labels.data == outputs.max(1)[1])
# Accuracy = number of correct predictions divided by all predictions accuracy += equality.type_as(torch.FloatTensor()).mean() print("Test accuracy: {:.3f}".format(accuracy/len(dataloaders['valid'])))
Test accuracy: 0.973
It’s important to save your checkpoint
保存您的检查点很重要
model.class_to_idx = image_datasets['train'].class_to_idx
checkpoint = {'input_size': 2208, 'output_size': 102, 'epochs': epochs, 'batch_size': 64, 'model': models.densenet161(pretrained=True), 'classifier': classifier, 'scheduler': sched, 'optimizer': optimizer.state_dict(), 'state_dict': model.state_dict(), 'class_to_idx': model.class_to_idx } torch.save(checkpoint, 'checkpoint.pth')
You don’t have to save all of the parameters, but I’m including them here as an example. This checkpoint specifically saves the model with a pre-trained densenet161 architecture, but if you want to save your checkpoint with the two-choice option, you can absolutely do that. Simply adjust the input size and model.
您不必保存所有参数,但我在此处以示例的方式包含它们。 该检查点专门使用预先训练的densitynet161架构保存模型,但是如果要使用“二选一”选项保存检查点,则绝对可以这样做。 只需调整输入大小和模型。
Now you’re able to load your checkpoint. If you’re submitting your project into the Udacity workspace, things can get a little tricky. Here’s some help with troubleshooting your checkpoint load.
现在,您可以加载检查点了。 如果要将项目提交到Udacity工作区,则可能会有些棘手。 这是一些故障排除检查点负载的帮助 。
You can check your keys by running
您可以通过运行来检查密钥
ckpt = torch.load('checkpoint.pth')ckpt.keys()
Then load and rebuild your model!
然后加载并重建模型!
def load_checkpoint(filepath): checkpoint = torch.load(filepath) model = checkpoint['model'] model.classifier = checkpoint['classifier'] model.load_state_dict(checkpoint['state_dict']) model.class_to_idx = checkpoint['class_to_idx'] optimizer = checkpoint['optimizer'] epochs = checkpoint['epochs'] for param in model.parameters(): param.requires_grad = False return model, checkpoint['class_to_idx']
model, class_to_idx = load_checkpoint('checkpoint.pth')
Want to keep going? It’s a good idea to do some image preprocessing and inference for classification. Go ahead and define your image path and open an image:
想继续吗? 对图像进行一些图像预处理和推断是一个好主意。 继续并定义图像路径并打开图像:
image_path = 'flower_data/valid/102/image_08006.jpg'img = Image.open(image_path)
Process your image and take a look at a processed image:
处理您的图像并查看已处理的图像:
def process_image(image): ''' Scales, crops, and normalizes a PIL image for a PyTorch model, returns an Numpy array ''' # Process a PIL image for use in a PyTorch model # tensor.numpy().transpose(1, 2, 0) preprocess = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) image = preprocess(image) return image
def imshow(image, ax=None, title=None): """Imshow for Tensor.""" if ax is None: fig, ax = plt.subplots() # PyTorch tensors assume the color channel is the first dimension # but matplotlib assumes is the third dimension image = image.numpy().transpose((1, 2, 0)) # Undo preprocessing mean = np.array([0.485, 0.456, 0.406]) std = np.array([0.229, 0.224, 0.225]) image = std * image + mean # Image needs to be clipped between 0 and 1 or it looks like noise when displayed image = np.clip(image, 0, 1) ax.imshow(image) return ax
with Image.open('flower_data/valid/102/image_08006.jpg') as image: plt.imshow(image)
model.class_to_idx = image_datasets['train'].class_to_idx
Create a function for prediction:
创建一个预测函数:
def predict2(image_path, model, topk=5): ''' Predict the class (or classes) of an image using a trained deep learning model. ''' # Implement the code to predict the class from an image file img = Image.open(image_path) img = process_image(img) # Convert 2D image to 1D vector img = np.expand_dims(img, 0) img = torch.from_numpy(img) model.eval() inputs = Variable(img).to(device) logits = model.forward(inputs) ps = F.softmax(logits,dim=1) topk = ps.cpu().topk(topk) return (e.data.numpy().squeeze().tolist() for e in topk)
Once the images are in the correct format, you can write a function to make predictions with your model. One common practice is to predict the top 5 or so (usually called top-KK) most probable classes. You’ll want to calculate the class probabilities then find the KK largest values.
一旦图像格式正确,您就可以编写一个函数来对模型进行预测。 一种常见的做法是预测前5个左右(通常称为top-KK)最可能的类别。 您将要计算类别概率,然后找到KK的最大值。
To get the top KK largest values in a tensor use k.topk(). This method returns both the highest k probabilities and the indices of those probabilities corresponding to the classes. You need to convert from these indices to the actual class labels using class_to_idx, which you added to the model or from the Image Folder you used to load the data. Make sure to invert the dictionary so you get a mapping from index to class as well.
要获取张量中的KK最大值,请使用k.topk()。 此方法既返回最高的k个概率,又返回对应于类的那些概率的索引。 您需要使用添加到模型中的class_to_idx或用于加载数据的图像文件夹将这些索引转换为实际的类标签。 确保反转字典,以便您也获得从索引到类的映射。
This method should take a path to an image and a model checkpoint, then return the probabilities and classes.
此方法应采用图像的路径和模型检查点,然后返回概率和类。
img_path = 'flower_data/valid/18/image_04252.jpg'probs, classes = predict2(img_path, model.to(device))print(probs)print(classes)flower_names = [cat_to_name[class_names[e]] for e in classes]print(flower_names)
I was pretty pleased with how my model performed!
我对模型的表现感到非常满意!
[0.9999195337295532, 1.4087702766119037e-05, 1.3897360986447893e-05, 1.1400215043977369e-05, 6.098791800468462e-06][12, 86, 7, 88, 40]['peruvian lily', 'desert-rose', 'king protea', 'magnolia', 'sword lily']
Basically, it’s nearly 100% likely that the image I specified is a Peruvian Lily. Want to take a look? Try using matplotlib to plot the probabilities for the top five classes in a bar graph along with the input image:
基本上,我指定的图像是秘鲁百合的可能性接近100%。 想看看吗? 尝试使用matplotlib在条形图中与输入图像一起绘制前五类的概率:
def view_classify(img_path, prob, classes, mapping): ''' Function for viewing an image and it's predicted classes. ''' image = Image.open(img_path)
fig, (ax1, ax2) = plt.subplots(figsize=(6,10), ncols=1, nrows=2) flower_name = mapping[img_path.split('/')[-2]] ax1.set_title(flower_name) ax1.imshow(image) ax1.axis('off') y_pos = np.arange(len(prob)) ax2.barh(y_pos, prob, align='center') ax2.set_yticks(y_pos) ax2.set_yticklabels(flower_names) ax2.invert_yaxis() # labels read top-to-bottom ax2.set_title('Class Probability')
view_classify(img_path, probs, classes, cat_to_name)
You should see something like this:
您应该会看到以下内容:
I’ve got to say, I’m pretty happy with that! I recommend testing a few other images to see how close your predictions are on a variety of images.
我必须说,对此我感到非常满意! 我建议测试其他一些图像,以查看各种图像上的预测有多接近。
Now it’s time to make a model of your own and let me know how it goes in the responses below!
现在是时候建立自己的模型了,让我知道它在下面的响应中是如何进行的!
Have you finished your deep learning or machine learning model, but you don’t know what to do with it next? Why not deploy it to the internet?
您是否已经完成了深度学习或机器学习模型,但是您不知道下一步该怎么做? 为什么不将其部署到Internet?
Get your model out there so everyone can see it!
将您的模型放到那里,以便所有人都能看到!
Check out this article to learn how to deploy your machine learning model with Flask!
翻译自: https://www.freecodecamp.org/news/how-to-build-the-best-image-classifier-3c72010b3d55/
深度学习图像分类精度