Cách xây dựng trình phân loại hình ảnh với độ chính xác cao hơn 97%

Một kế hoạch chi tiết rõ ràng và đầy đủ để thành công

Làm thế nào để bạn dạy một máy tính nhìn vào một hình ảnh và xác định chính xác nó là một bông hoa? Làm thế nào để bạn dạy một máy tính để xem hình ảnh của một bông hoa và sau đó cho bạn biết chính xác đó là loài hoa gì khi thậm chí bạn không biết nó là loài gì?

Tôi se cho bạn xem!

Bài viết này sẽ đưa bạn qua những điều cơ bản để tạo một bộ phân loại hình ảnh với PyTorch. Bạn có thể tưởng tượng sử dụng một cái gì đó như thế này trong một ứng dụng điện thoại cho bạn biết tên của bông hoa mà máy ảnh của bạn đang nhìn. Bạn có thể, nếu bạn muốn, huấn luyện bộ phân loại này và sau đó xuất nó để sử dụng trong một ứng dụng của riêng bạn.

Những gì bạn làm từ đây phụ thuộc hoàn toàn vào bạn và trí tưởng tượng của bạn.

Tôi kết hợp bài viết này với bất kỳ ai ngoài kia, những người hoàn toàn mới với tất cả những điều này và tìm kiếm một nơi để bắt đầu. Nó phụ thuộc vào bạn để lấy thông tin này, cải thiện nó và biến nó thành của riêng bạn!

Nếu bạn muốn xem sổ ghi chép, bạn có thể tìm thấy nó ở đây.

Bởi vì trình phân loại hình ảnh PyTorch này được xây dựng như một dự án cuối cùng cho chương trình Udacity, mã này dựa trên mã từ Udacity, do đó, dựa trên tài liệu chính thức của PyTorch. Udacity cũng cung cấp một tệp JSON để ánh xạ nhãn. Tập tin đó có thể được tìm thấy trong repo GitHub này.

Thông tin về bộ dữ liệu hoa có thể được tìm thấy ở đây. Tập dữ liệu bao gồm một thư mục riêng cho mỗi trong số 102 lớp hoa. Mỗi bông hoa được dán nhãn là một số và mỗi thư mục được đánh số chứa một số tệp .jpg.

Bắt đầu nào!

Ảnh của Annie Spratt trên Bapt

Vì đây là mạng thần kinh sử dụng bộ dữ liệu lớn hơn CPU của tôi có thể xử lý trong bất kỳ khoảng thời gian hợp lý nào, tôi đã tiếp tục và thiết lập trình phân loại hình ảnh của mình trong Google Colab. Colab thực sự tuyệt vời vì nó cung cấp GPU miễn phí. (Nếu bạn mới sử dụng Colab, hãy xem bài viết này về việc bắt đầu với Google Colab!)

Bởi vì tôi đang sử dụng Colab, tôi cần bắt đầu bằng cách nhập PyTorch. Bạn không cần phải làm điều này nếu bạn không sử dụng Colab.

*** CẬP NHẬT! (29/11) *** Colab hiện hỗ trợ PyTorch bản địa !!! Bạn không nên chạy mã bên dưới, nhưng tôi sẽ để nó lại trong trường hợp có ai gặp vấn đề gì!

# Nhập PyTorch nếu sử dụng Google Colab
# http://pytorch.org/
từ nhập os.path tồn tại
từ wheel.pep425tags nhập get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{} {} - {}'. định dạng (get_abbr_impl (), get_impl_ver (), get_abi_tag ())
cudaDefput =! ldconfig -p | grep cudart.so | sed -e 's /.* \. \ ([0-9] * \) \. \ ([0-9] * \) $ / cu \ 1 \ 2 / '
máy gia tốc = cudaDefput [0] nếu tồn tại ('/ dev / nvidia0') khác 'cpu'
! Pip cài đặt -q http
ngọn đuốc nhập khẩu

Sau đó, sau khi gặp một số rắc rối với Gối (lỗi Bẻ khóa trong Colab!), Tôi chỉ tiếp tục và chạy nó:

PIL nhập khẩu
in (PIL.PILLOW_VERSION)

Nếu bạn nhận được bất cứ điều gì dưới 5.3.0, hãy sử dụng menu thả xuống bên dưới Thời gian chạy trực tiếp để Khởi động lại thời gian chạy và chạy lại ô này. Bạn sẽ được tốt để đi!

Bạn sẽ muốn sử dụng GPU cho dự án này, điều này cực kỳ đơn giản để thiết lập trên Colab. Bạn chỉ cần vào menu thả xuống của bộ thực tập thời gian thực trực tuyến, chọn kiểu thay đổi thời gian chạy kiểu Thay thế và sau đó chọn bộ nhớ GPU GPU trong trình đơn thả xuống của trình tăng tốc phần cứng!

Sau đó tôi thích chạy

train_on_gpu = Torch.cuda.is_av Available ()
nếu không train_on_gpu:
    in ('Bummer! Đào tạo về CPU ...')
khác:
    in ('Bạn rất tốt để đi! Đào tạo về GPU ...')

chỉ để đảm bảo rằng nó làm việc. Sau đó chạy

device = Torch.device ("cuda: 0" nếu Torch.cuda.is_av Available () khác "cpu")

để xác định thiết bị.

Sau này, nhập các tệp. Có rất nhiều cách để làm điều này, bao gồm cả việc gắn Google Drive nếu bạn có bộ dữ liệu của mình được lưu trữ ở đó, điều này thực sự rất đơn giản. Mặc dù tôi đã không phát hiện ra rằng đó là giải pháp hữu ích nhất, tôi đã bao gồm cả giải pháp dưới đây, chỉ vì nó rất dễ dàng và hữu ích.

từ ổ đĩa nhập khẩu google.colab
drive.mount ('/ content / gdrive')

Sau đó, bạn sẽ thấy một liên kết, nhấp vào đó, cho phép truy cập, sao chép mã bật lên, dán nó vào hộp, nhấn enter và bạn sẽ rất tốt! Nếu bạn không thấy ổ đĩa của bạn ở ô bên trái, chỉ cần nhấn vào refresh refresh và nó sẽ hiển thị.

(Chạy ô, nhấp vào liên kết, sao chép mã trên trang, dán mã vào hộp, nhấn enter và bạn sẽ thấy điều này khi bạn gắn ổ đĩa thành công):

Nó thực sự siêu dễ dàng!

Tuy nhiên, nếu bạn đã tải xuống một liên kết tệp zip được chia sẻ (việc này dễ dàng hơn và nhanh hơn cho dự án này), bạn có thể sử dụng:

!
! giải nén

Ví dụ:

! wget -cq https://s3.amazonaws.com/content.udacity-data.com/cifts/nd188/flower_data.zip
! giải nén -qq hoa_data.zip

Điều đó sẽ cung cấp cho bạn dữ liệu hoa Udacity trong vài giây!

(Nếu bạn đang tải lên các tệp nhỏ, bạn chỉ có thể tải chúng trực tiếp bằng một số mã đơn giản. Tuy nhiên, nếu bạn muốn, bạn cũng có thể chỉ cần đi về phía bên trái của màn hình và nhấp vào Tải lên các tập tin cảm thấy như chạy một số mã đơn giản để lấy một tệp cục bộ.)

Sau khi tải dữ liệu, tôi đã nhập các thư viện tôi muốn sử dụng:

% matplotlib nội tuyến
% config InlineBackend.figure_format = 'retina'
thời gian nhập khẩu
nhập khẩu json
nhập bản sao
nhập matplotlib.pyplot dưới dạng plt
nhập khẩu seaborn như sns
nhập numpy như np
PIL nhập khẩu
từ hình ảnh nhập khẩu PIL
từ bộ sưu tập nhập OrderedDict
ngọn đuốc nhập khẩu
từ đuốc nhập nn, tối ưu
từ Torch.optim nhập lr_scheduler
từ Torch.aut giác nhập khẩu Biến
nhập khẩu đèn pin
từ bộ dữ liệu nhập khẩu Torchvision, mô hình, biến đổi
từ Torch.utils.data.sampler nhập SubsetRandomSampler
nhập khẩu ngọn đuốc.nn như nn
nhập khẩu đèn pin.nn.chức năng là F

Tiếp đến là biến đổi dữ liệu! Bạn muốn đảm bảo sử dụng một số loại biến đổi khác nhau trên tập huấn luyện của mình để giúp chương trình của bạn học được nhiều nhất có thể. Bạn có thể tạo một mô hình mạnh mẽ hơn bằng cách đào tạo nó trên các hình ảnh lật, xoay và cắt.

Có nghĩa là độ lệch chuẩn được cung cấp để chuẩn hóa các giá trị hình ảnh trước khi chuyển chúng vào mạng của chúng tôi, nhưng chúng cũng có thể được tìm thấy bằng cách xem xét các giá trị độ lệch trung bình và độ lệch chuẩn của các kích thước khác nhau của các thang đo hình ảnh. Các tài liệu chính thức là vô cùng hữu ích ở đây!

Đối với phân loại hình ảnh của tôi, tôi giữ nó đơn giản với:

data_transforms = {
    'Train': Transforms.Compose ([
        biến đổi.RandomRotation (30),
        biến đổi.RandomResizedCrop (224),
        biến đổi.RandomHTHERFlip (),
        biến đổi.ToTensor (),
        biến đổi. Chuẩn hóa ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ]),
    'hợp lệ': Transforms.Compose ([
        biến đổi.Resize (256),
        biến đổi.CenterCrop (224),
        biến đổi.ToTensor (),
        biến đổi. Chuẩn hóa ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
}
# Tải các bộ dữ liệu bằng ImageFolder
image_datasets = {x: dataets.ImageFolder (os.path.join (data_dir, x),
                                          data_transforms [x])
                  cho x trong ['tàu', 'hợp lệ']}
# Sử dụng bộ dữ liệu hình ảnh và biểu mẫu, xác định bộ tải dữ liệu
batch_size = 64
dataloaders = {x: Torch.utils.data.DataLoader (image_datasets [x], batch_size = batch_size,
                                             xáo trộn = Đúng, num_workers = 4)
              cho x trong ['tàu', 'hợp lệ']}
class_names = image_datasets ['train']. các lớp
tập dữ liệu_sizes = {x: len (image_datasets [x]) cho x trong ['train', 'hợp lệ']}
class_names = image_datasets ['train']. các lớp

Như bạn có thể thấy ở trên, tôi cũng đã định nghĩa kích thước lô, bộ tải dữ liệu và tên lớp trong mã ở trên.

Để xem nhanh dữ liệu và kiểm tra thiết bị của tôi, tôi đã chạy:

in (tập dữ liệu)
in (thiết bị)
{'tàu': 6552, 'hợp lệ': 818}
cuda: 0

Tiếp theo, chúng ta cần thực hiện một số ánh xạ từ số nhãn và tên hoa thực tế. Udacity cung cấp một tệp JSON để ánh xạ này được thực hiện đơn giản.

với open ('cat_to_name.json', 'r') là f:
    cat_to_name = json.load (f)

Để kiểm tra trình tải dữ liệu, hãy chạy:

hình ảnh, nhãn = next (iter (bộ tải dữ liệu ['train']))
rand_idx = np.random.randint (len (hình ảnh))
# In (rand_idx)
print ("nhãn: {}, class: {}, name: {}". format (nhãn [rand_idx] .item (),
                                               class_names [nhãn [rand_idx] .item ()],
                                               cat_to_name [class_names [nhãn [rand_idx] .item ()]]))

Bây giờ nó bắt đầu thú vị hơn nữa! Một số mô hình trong vài năm qua đã được tạo ra bởi những người ở xa, có trình độ cao hơn nhiều so với hầu hết chúng ta để tái sử dụng trong các vấn đề về thị giác máy tính. PyTorch giúp dễ dàng tải các mô hình được đào tạo trước và xây dựng trên chúng, đó chính xác là những gì chúng tôi sẽ làm cho dự án này. Sự lựa chọn của mô hình là hoàn toàn tùy thuộc vào bạn!

Một số mô hình được đào tạo trước phổ biến nhất, như ResNet, AlexNet và VGG, đến từ Thử thách ImageNet. Những mô hình được đào tạo trước này cho phép những người khác nhanh chóng đạt được kết quả tiên tiến trong tầm nhìn máy tính mà không cần số lượng lớn sức mạnh máy tính, sự kiên nhẫn và thời gian. Tôi thực sự đã có kết quả tuyệt vời với DenseNet và quyết định sử dụng DenseNet161, điều này mang lại cho tôi kết quả rất tốt tương đối nhanh chóng.

Bạn có thể nhanh chóng thiết lập điều này bằng cách chạy

model = model.densenet161 (Pretrained = True)

nhưng nó có thể thú vị hơn để cung cấp cho bạn một sự lựa chọn về mô hình, trình tối ưu hóa và lịch trình. Để thiết lập lựa chọn trong kiến ​​trúc, hãy chạy

model_name = 'densenet' #vgg
if model_name == 'densenet':
    model = model.densenet161 (Pretrained = True)
    num_in_features = 2208
    in (mô hình)
elif model_name == 'vgg':
    model = model.vgg19 (Pretrained = True)
    num_in_features = 25088
    in (model. classifier)
khác:
    in ("Mô hình không xác định, vui lòng chọn 'densenet' hoặc 'vgg'")

cho phép bạn nhanh chóng thiết lập một mô hình thay thế.

Sau đó, bạn có thể bắt đầu xây dựng trình phân loại của mình, sử dụng các tham số phù hợp nhất với bạn. Tôi đã đi trước và xây dựng

cho param trong model.parameter ():
    param.requires_grad = Sai
def build_ classifier (num_in_features, hidden_layers, num thừng_features):
   
    phân loại = nn.Sequential ()
    if hidden_layers == Không có:
        phân loại.add_module ('fc0', nn.Linear (num_in_features, 102))
    khác:
        layer_sizes = zip (hidden_layers [: - 1], hidden_layers [1:])
        classifier.add_module ('fc0', nn.Linear (num_in_features, hidden_layers [0]))
        phân loại.add_module ('relu0', nn.ReLU ())
        phân loại.add_module ('drop0', nn.Dropout (.6))
        phân loại.add_module ('relu1', nn.ReLU ())
        phân loại.add_module ('drop1', nn.Dropout (.5))
        đối với i, (h1, h2) trong liệt kê (layer_sizes):
            phân loại.add_module ('fc' + str (i + 1), nn.Linear (h1, h2))
            phân loại.add_module ('relu' + str (i + 1), nn.ReLU ())
            classifier.add_module ('drop' + str (i + 1), nn.Dropout (.5))
        classifier.add_module ('đầu ra', nn.Linear (hidden_layers [-1], num thừng_features))
        
    phân loại trả về

cho phép một cách dễ dàng để thay đổi số lượng các lớp ẩn mà tôi sử dụng, cũng như nhanh chóng điều chỉnh tỷ lệ bỏ học. Bạn có thể quyết định thêm các lớp ReLU và bỏ học bổ sung để cải thiện mô hình của bạn một cách tinh vi hơn.

Tiếp theo, làm việc về đào tạo các tham số phân loại của bạn. Tôi quyết định đảm bảo rằng tôi chỉ đào tạo các tham số phân loại ở đây trong khi có các tham số tính năng bị đóng băng. Bạn có thể sáng tạo như bạn muốn với trình tối ưu hóa, tiêu chí và trình lập lịch biểu của bạn. Tiêu chí là phương pháp được sử dụng để đánh giá mức độ phù hợp của mô hình, trình tối ưu hóa là phương pháp tối ưu hóa được sử dụng để cập nhật trọng số và bộ lập lịch cung cấp các phương pháp khác nhau để điều chỉnh tốc độ học và kích thước bước được sử dụng trong quá trình tối ưu hóa.

Hãy thử càng nhiều tùy chọn và kết hợp càng tốt để xem điều gì mang lại cho bạn kết quả tốt nhất. Bạn có thể xem tất cả các tài liệu chính thức ở đây. Tôi khuyên bạn nên xem nó và đưa ra quyết định của riêng bạn về những gì bạn muốn sử dụng. Bạn không có nghĩa đen là có vô số tùy chọn ở đây, nhưng chắc chắn sẽ có cảm giác như vậy khi bạn bắt đầu chơi xung quanh!

hidden_layers = Không có
classifier = build_ classifier (num_in_features, hidden_layers, 102)
in (phân loại)
# Chỉ đào tạo các tham số phân loại, tham số tính năng bị đóng băng
if model_name == 'densenet':
    model. classifier = classifier
    tiêu chí = nn.CrossEntropyLoss ()
    tối ưu hóa = tối ưu.Adadelta (model.parameter ())
    calendar = Optim.lr_scheduler.StepLR (trình tối ưu hóa, step_size = 4)
elif model_name == 'vgg':
    model. classifier = classifier
    tiêu chí = nn.NLLLoss ()
    Trình tối ưu hóa = Optim.Adam (model. classifier.parameter (), lr = 0,0001)
    calendar = lr_scheduler.StepLR (trình tối ưu hóa, step_size = 4, gamma = 0.1)
khác:
    vượt qua

Bây giờ, thời gian đào tạo mô hình của bạn.

# Chuyển thể từ https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html
def train_model (mô hình, tiêu chí, trình tối ưu hóa, lịch trình, num_epochs = 5):
    kể từ = time.time ()
best_model_wts = copy.deepcopy (model.state_dict ())
    tốt nhất_acc = 0,0
cho epoch trong phạm vi (num_epochs):
        in (định dạng 'Epoch {} / {}'. (epoch + 1, num_epochs))
        in ('-' * 10)
# Mỗi kỷ nguyên có một giai đoạn đào tạo và xác nhận
        cho giai đoạn trong ['tàu', 'hợp lệ']:
            nếu pha == 'tàu':
                model.train () # Đặt mô hình sang chế độ đào tạo
            khác:
                model.eval () # Đặt mô hình để đánh giá chế độ
running_loss = 0,0
            running_corrects = 0
# Lặp lại dữ liệu.
            cho đầu vào, nhãn trong bộ tải dữ liệu [pha]:
                đầu vào = đầu vào.to (thiết bị)
                nhãn = nhãn.to (thiết bị)
# Không độ dốc tham số
                trình tối ưu hóa.zero_grad ()
# Ở đằng trước
                # theo dõi lịch sử nếu chỉ trong tàu
                với Torch.set_grad_enables (phase == 'train'):
                    đầu ra = mô hình (đầu vào)
                    _, pres = Torch.max (đầu ra, 1)
                    mất = tiêu chí (đầu ra, nhãn)
# Backward + chỉ tối ưu hóa nếu trong giai đoạn đào tạo
                    nếu pha == 'tàu':
                        # calendar.step ()
                        mất mát.backward ()
                        
                        trình tối ưu hóa.step ()
# Số liệu thống kê
                running_loss + = loss.item () * input.size (0)
                running_corrects + = Torch.sum (tiền tố == nhãn.data)
epoch_loss = running_loss / data_sizes [phase]
            epoch_acc = running_corrects.double () / tập dữ liệu_sizes [phase]
print ('{} Mất: {: .4f} Acc: {: .4f}'.
                pha, epoch_loss, epoch_acc))
# Sao chép sâu mô hình
            if phase == 'hợp lệ' và epoch_acc> best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy (model.state_dict ())
in()
time_elapsed = time.time () - kể từ
    print ('Hoàn thành đào tạo trong {: .0f} m {: .0f} s'.format (
        time_elapsed // 60, time_elapsed% 60))
    in ('Định dạng val tốt nhất: {: 4f}'. định dạng (best_acc))
# Tải trọng lượng mô hình tốt nhất
    mô hình.load_state_dict (best_model_wts)
    
    mô hình trở lại
kỷ nguyên = 30
model.to (thiết bị)
model = train_model (mô hình, tiêu chí, trình tối ưu hóa, lịch trình, kỷ nguyên)

Tôi muốn có thể theo dõi các kỷ nguyên của mình một cách dễ dàng và cũng theo dõi thời gian trôi qua khi mô hình của tôi đang chạy. Mã ở trên bao gồm cả hai, và kết quả là khá tốt! Bạn có thể thấy rằng mô hình đang nhanh chóng học hỏi và độ chính xác trên bộ xác nhận nhanh chóng đạt hơn 95% vào thời điểm 7!

Đại Kỷ Nguyên 1/30
----------
Mất tàu: 2.4793 Acc: 0.4791
Mất hợp lệ: 0.9688 Acc: 0.8191

Kỷ nguyên 2/30
----------
Mất tàu: 0.8288 Acc: 0.8378
Mất hợp lệ: 0,4714 Acc: 0,9010

Kỷ nguyên 3/30
----------
Mất tàu: 0,5191 Acc: 0,8890
Mất hợp lệ: 0.3197 Acc: 0.9181

Kỷ nguyên 4/30
----------
Mất tàu: 0,4064 Acc: 0,9095
Mất hợp lệ: 0,2975 Acc: 0,9169

Kỷ nguyên 5/30
----------
Mất tàu: 0,3401 Acc: 0,9214
Mất hợp lệ: 0,2486 Acc: 0,9401

Kỷ nguyên 6/30
----------
Mất tàu: 0,311 Acc: 0,9303
Mất hợp lệ: 0,2153 Acc: 0,9487

Kỷ nguyên 7/30
----------
Mất tàu: 0,2987 Acc: 0,9298
Mất hợp lệ: 0,1969 Acc: 0,9584
...
Đào tạo hoàn thành trong 67m 43s
Giá trị tốt nhất Acc: 0,973105

Bạn có thể thấy rằng việc chạy mã này trên Google Colab với GPU chỉ mất hơn một giờ.

Bây giờ là thời gian để đánh giá

mô hình.eval ()
độ chính xác = 0
cho các đầu vào, nhãn trong bộ tải dữ liệu ['hợp lệ']:
    đầu vào, nhãn = input.to (thiết bị), nhãn.to (thiết bị)
    đầu ra = mô hình (đầu vào)
    
    # Lớp có xác suất cao nhất là lớp dự đoán của chúng tôi
    đẳng thức = (nhãn.data == output.max (1) [1])
# Độ chính xác = số dự đoán đúng chia cho tất cả các dự đoán
    độ chính xác + = Equality.type_as (Torch.FloatTensor ()). mean ()
    
print ("Độ chính xác kiểm tra: {: .3f}". định dạng (độ chính xác / len (bộ tải dữ liệu ['hợp lệ'])))
Kiểm tra độ chính xác: 0,973

Nó rất quan trọng để lưu điểm kiểm tra của bạn

model.group_to_idx = image_datasets ['train']. class_to_idx
điểm kiểm tra = {'input_size': 2208,
              'output_size': 102,
              'epochs': kỷ nguyên,
              'batch_size': 64,
              'model': model.densenet161 (Pretrained = True),
              'phân loại': phân loại,
              'lập lịch': lịch trình,
              'Trình tối ưu hóa': trình tối ưu hóa.state_dict (),
              'state_dict': model.state_dict (),
              'class_to_idx': model. class_to_idx
             }
   
Torch.save (điểm kiểm tra, 'checkpoint.pth')

Bạn không thể lưu tất cả các tham số, nhưng tôi đã bao gồm chúng ở đây làm ví dụ. Điểm kiểm tra này đặc biệt lưu mô hình với kiến ​​trúc densenet161 được đào tạo trước, nhưng nếu bạn muốn lưu điểm kiểm tra của mình với tùy chọn hai lựa chọn, bạn hoàn toàn có thể làm điều đó. Đơn giản chỉ cần điều chỉnh kích thước đầu vào và mô hình.

Bây giờ bạn có thể tải điểm kiểm tra của bạn. Nếu bạn có thể gửi dự án của mình vào không gian làm việc của Udacity, mọi thứ có thể hơi rắc rối. Ở đây, một số trợ giúp với việc khắc phục sự cố tải điểm kiểm tra của bạn.

Bạn có thể kiểm tra chìa khóa bằng cách chạy

ckpt = Torch.load ('checkpoint.pth')
ckpt.key ()

Sau đó tải và xây dựng lại mô hình của bạn!

def load_checkpoint (filepath):
    điểm kiểm tra = Torch.load (filepath)
    mô hình = điểm kiểm tra ['mô hình']
    model. classifier = checkpoint ['classifier']
    model.load_state_dict (điểm kiểm tra ['state_dict'])
    model.group_to_idx = checkpoint ['class_to_idx']
    trình tối ưu hóa = điểm kiểm tra ['trình tối ưu hóa']
    epochs = điểm kiểm tra ['epochs']
    
    cho param trong model.parameter ():
        param.requires_grad = Sai
        
    mô hình trả về, điểm kiểm tra ['class_to_idx']
mô hình, class_to_idx = load_checkpoint ('checkpoint.pth')

Bạn muốn tiếp tục đi? Nó là một ý tưởng tốt để thực hiện một số tiền xử lý hình ảnh và suy luận để phân loại. Đi trước và xác định đường dẫn hình ảnh của bạn và mở một hình ảnh:

image_path = 'hoa_data / hợp lệ / 102 / image_08006.jpg'
img = Image.open (image_path)

Xử lý hình ảnh của bạn và xem hình ảnh được xử lý:

def process_image (hình ảnh):
    '' 'Cân, cắt xén và bình thường hóa hình ảnh PIL cho mô hình PyTorch,
        trả về một mảng Numpy
    '' '
    # Xử lý hình ảnh PIL để sử dụng trong mô hình PyTorch
    # tenor.numpy (). hoán vị (1, 2, 0)
    tiền xử lý = Transforms.Compose ([
        biến đổi.Resize (256),
        biến đổi.CenterCrop (224),
        biến đổi.ToTensor (),
        biến đổi. Bình thường hóa (mean = [0.485, 0.456, 0.406],
                             std = [0,229, 0,224, 0,225])
    ])
    hình ảnh = tiền xử lý (hình ảnh)
    hình ảnh trở lại
def imshow (hình ảnh, ax = Không, tiêu đề = Không):
    "" "Imshow cho Tenor." ""
    nếu ax là Không có:
        hình, ax = plt.subplots ()
    
    Các thang đo # PyTorch giả sử kênh màu là thứ nguyên đầu tiên
    # nhưng giả sử matplotlib là chiều thứ ba
    image = image.numpy (). hoán vị ((1, 2, 0))
    
    # Hoàn tác tiền xử lý
    trung bình = np.array ([0.485, 0.456, 0.406])
    std = np.array ([0.229, 0.224, 0.225])
    hình ảnh = std * hình ảnh + có nghĩa là
    
    # Hình ảnh cần được cắt giữa 0 và 1 hoặc có vẻ như nhiễu khi hiển thị
    hình ảnh = np.clip (hình ảnh, 0, 1)
    
    ax.imshow (hình ảnh)
    
    rìu trở lại
với Image.open ('hoa_data / hợp lệ / 102 / image_08006.jpg') dưới dạng hình ảnh:
    plt.imshow (hình ảnh)
model.group_to_idx = image_datasets ['train']. class_to_idx

Tạo một chức năng để dự đoán:

def dự đoán2 (image_path, model, topk = 5):
    '' 'Dự đoán lớp (hoặc lớp) của hình ảnh bằng mô hình học sâu được đào tạo.
    '' '
    
    # Thực hiện mã để dự đoán lớp từ tệp hình ảnh
    img = Image.open (image_path)
    img = process_image (img)
    
    # Chuyển đổi hình ảnh 2D thành vector 1D
    img = np.Exand_dims (img, 0)
    
    
    img = Torch.from_numpy (img)
    
    mô hình.eval ()
    đầu vào = Biến (img) .to (thiết bị)
    logits = model.forward (đầu vào)
    
    ps = F.softmax (đăng nhập, mờ = 1)
    topk = ps.cpu (). topk (topk)
    
    return (e.data.numpy (). bóp (). tolist () cho e trong topk)

Khi hình ảnh ở định dạng chính xác, bạn có thể viết một hàm để đưa ra dự đoán với mô hình của mình. Một thực tế phổ biến là dự đoán top 5 hoặc hơn (thường được gọi là top-KK) các lớp có thể xảy ra nhất. Bạn muốn tính toán xác suất của lớp sau đó tìm các giá trị lớn nhất của KK.

Để có được các giá trị KK lớn nhất hàng đầu trong một tenxơ, hãy sử dụng k.topk (). Phương thức này trả về cả xác suất k cao nhất và chỉ số của các xác suất đó tương ứng với các lớp. Bạn cần chuyển đổi từ các chỉ mục này sang nhãn lớp thực tế bằng class_to_idx, mà bạn đã thêm vào mô hình hoặc từ Thư mục hình ảnh bạn đã sử dụng để tải dữ liệu. Đảm bảo đảo ngược từ điển để bạn cũng có được ánh xạ từ chỉ mục đến lớp.

Phương thức này sẽ đưa một đường dẫn đến một hình ảnh và một điểm kiểm tra mô hình, sau đó trả về xác suất và các lớp.

img_path = 'hoa_data / hợp lệ / 18 / image_04252.jpg'
probs, class = dự đoán2 (img_path, model.to (thiết bị))
in (probs)
in (lớp)
hoa_names = [cat_to_name [class_names [e]] cho e trong lớp]
in (hoa_names)

Tôi khá hài lòng với cách người mẫu của tôi thực hiện!

[0,9999953729293232
[12, 86, 7, 88, 40]
['lily peruvian', 'sa mạc hoa hồng', 'king protea', 'mộc lan', 'lily lily']

Về cơ bản, nó có khả năng gần như 100% rằng hình ảnh tôi chỉ định là một Lily Peru. Bạn muốn xem qua? Hãy thử sử dụng matplotlib để vẽ các xác suất cho năm lớp hàng đầu trong biểu đồ thanh cùng với hình ảnh đầu vào:

def view_groupify (img_path, thăm dò, các lớp, ánh xạ):
    '' 'Chức năng để xem một hình ảnh và đó là các lớp dự đoán.
    '' '
    hình ảnh = Image.open (img_path)
fig, (ax1, ax2) = plt.subplots (figsize = (6,10), ncols = 1, nss = 2)
    hoa_name = ánh xạ [img_path.split ('/') [- 2]]
    ax1.set_title (hoa_name)
    ax1.imshow (hình ảnh)
    ax1.axis ('tắt')
    
    y_pose = np.arange (len (thăm dò))
    ax2.barh (y_pose, prob, align = 'centre')
    ax2.set_yticks (y_pose)
    ax2.set_yticklabels (hoa_names)
    ax2.invert_yaxis () # nhãn đọc từ trên xuống dưới
    ax2.set_title ('Xác suất lớp')
view_groupify (img_path, probs, class, cat_to_name)

Bạn sẽ thấy một cái gì đó như thế này:

Tôi phải nói, tôi rất vui vì điều đó! Tôi khuyên bạn nên thử nghiệm một vài hình ảnh khác để xem mức độ dự đoán của bạn gần với nhiều hình ảnh khác nhau.

Bây giờ, thời gian để tạo ra một mô hình của riêng bạn và cho tôi biết làm thế nào nó đi trong các câu trả lời dưới đây!

Ảnh của Pez González trên Bapt

Bạn đã hoàn thành mô hình học tập sâu hoặc máy học, nhưng bạn không biết phải làm gì với nó tiếp theo? Tại sao không triển khai nó lên internet?

Đưa mô hình của bạn ra khỏi đó để mọi người có thể nhìn thấy nó!

Kiểm tra bài viết này để tìm hiểu cách triển khai mô hình học máy của bạn với Flask!