Jump to content
Compvision.ru
Sign in to follow this  
maxfashko

Расчет accuracy обученной модели

Recommended Posts

Добрый вечер. Интересует собственно как расчитывать точность на сегментированных нейронной сетью изображениях? Имеем тестовую выборку, пропущенную через нейронную сеть, в которой есть файлы разметки и собственно файлы сегментированные сетью. Теперь как мы можем по полученным изображениям выяснить их точность? Понятное дело, что сегментированные файлы должны стремиться к изображениям аннотации. Написал следующий скрипт для расчета точности:

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fileencoding=utf-8
#use only 2 classes
# object (60,40,222) color
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import os
from os import listdir
from os.path import isfile, join
labelPath = 'test/ground_truth'
segmentPath = 'test/segment'
resultFileName = 'test/result.txt'

labelList = []
segmentList = []
resultArr = []

#get files in dir
def list_files(path, files):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files

def main():
	mean = 0
	list_files(labelPath, labelList)
	list_files(segmentPath, segmentList)

	if len(labelList) != len(segmentList):
		print 'len '+labelPath+' != '+segmentPath
		return -1

	for i in range (len(labelList)):

		#label img
		imgLabel = Image.open(labelPath+'/'+labelList[i])
		w = imgLabel.size[0] #Определяем ширину. 
		h = imgLabel.size[1] #Определяем высоту. 	
		pixLabel = imgLabel.load() #Выгружаем значения пикселей.

		#segment img
		imgSegment = Image.open(segmentPath+'/'+segmentList[i])	
		pixSegment = imgSegment.load() #Выгружаем значения пикселей.

		amountPixObjLabel = 0
		amountPixLossLabel = 0

		#amount pixels with object
		for k in range(0, w):
			for l in range(0, h):
				if pixLabel[k,l][0:3] == (60, 40, 222):		#blue color object
					amountPixObjLabel+=1

		#search differences
		for k in range(0, w):
			for l in range(0, h):
				if pixLabel[k,l][0:3] != pixSegment[k,l][0:3]:
					amountPixLossLabel +=1

		#one pix = %
		onePix = float(100) / float(amountPixObjLabel)

		count = 100 - (amountPixLossLabel*onePix)
		mean += count
		resultArr.append(str(i)+' accuracy = '+str(count))
		print str(i)+' accuracy = '+str(count)

	print 'Mean accuracy = '+str(mean / len(labelList))
	resultArr.append('Mean accuracy = '+str(mean / len(labelList)))

	#write result
	resultFile = open(resultFileName, 'w')
	for item in resultArr:
  	    resultFile.write("%s\n" % item)

main()

Смысл такой: загружаем значения пикселей аннотированного изображения, затем делаем тоже самое с сегментированным изображением. Если в сегментированном изображении текущий пиксель отличается от пикселя в аннотированном, увеличиваем счетчик ошибочных пикселей по данному изображению. Затем расчитываем сколько пикселей составляет один процент от всех пикселей в объекте аннотированного изображения. И затем переводим наши ошибочные пиксели в проценты. Это и будет наша точность.

file: ground_truth

.0_пе.png

file: segment

0.png

Например для данного сообщения выводится значение accuracy = 96.9656336161

 

Share this post


Link to post
Share on other sites

Начать можно отсюда: https://en.wikipedia.org/wiki/F1_score  :)

И это пригодится: https://en.wikipedia.org/wiki/Precision_and_recall

Именно accuracy=(TP+TN)/(P+N), но это не самая объективная метрика.

Share this post


Link to post
Share on other sites
2 часа назад, Smorodov сказал:

Начать можно отсюда: https://en.wikipedia.org/wiki/F1_score  :)

И это пригодится: https://en.wikipedia.org/wiki/Precision_and_recall

Именно accuracy=(TP+TN)/(P+N), но это не самая объективная метрика.

Спасибо! Поделитесь пожалуйста, что означают P,  N ? 

Как я понял TP - это объект (синий), пиксели, которые верно сегментированы

TN - это фон (серый), пиксели, которые верно сегментированы

P, N - это кол-во файлов?

То есть проходим циклом по картинке забирая хорошие "синие" пиксели. Затем так же но берем уже хорошие "серые" пиксели? Складываем и делим на кол-во?

Share this post


Link to post
Share on other sites

TP - true positives - элементы классифицированные как объект и являющиеся объектом.

FP - false positives - элементы классифицированные как объект, но не являющиеся им.

TN - true negatives - элементы классифицированные как не объект и не являющиеся им.

FN - false negatives - элементы классифицированные как не объект, но являющиеся им.

P (positives) - все элементы, классифицированные как объект .

N - (negatives) все элементы, классифицированные как не объект.

  • Like 1

Share this post


Link to post
Share on other sites

Smorodov, в общем реализовал скрипт, расчитывающий accuracy:

Только вот в результате не уверен, слишком высокую точность выдает: accuracy = 0.996942198369 на изображении приведенном выше

1. В цикле подсчитываем кол-во P,N пикселей текущего изображения.

2. В цикле подсчитываем кол-во TN,TP пикселей текущего изображения, если текущий пиксель имеет одинаковое значение в изображениях ground_truth и segment

Взгляните пожалуйста на код:

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import os
from os import listdir
from os.path import isfile, join

labelPath = 'test/ground_truth'
segmentPath = 'test/segment'
resultFileName = 'test/result.txt'

labelList = []
segmentList = []
resultArr = []

colorClass1 = (60,40,222)		#object
colorClass2 = (128,128,128)		#background

#get files in dir
def list_files(path, files):
    # returns a list of names (with extension, without full path) of all files 
    # in folder path
    for name in os.listdir(path):
        if os.path.isfile(os.path.join(path, name)):
            files.append(name)
    return files

def main():

	#for calculation global value
	mean = 0
	TP_g = 0
	TN_g = 0
	P_g = 0
	N_g = 0

	list_files(labelPath, labelList)
	list_files(segmentPath, segmentList)

	if len(labelList) != len(segmentList):
		print 'len '+labelPath+' != '+segmentPath
		return -1

	for i in range (len(labelList)):

		TP = 0
		TN = 0
		P = 0
		N = 0

		#label img
		imgLabel = Image.open(labelPath+'/'+labelList[i])
		w = imgLabel.size[0] #Определяем ширину. 
		h = imgLabel.size[1] #Определяем высоту. 	
		pixLabel = imgLabel.load() #Выгружаем значения пикселей.

		#segment img
		imgSegment = Image.open(segmentPath+'/'+segmentList[i])	
		pixSegment = imgSegment.load() #Выгружаем значения пикселей.

		#calculate P, N (pixels of object and background)
		for k in range(0, w):
			for l in range(0, h):
				if pixSegment[k,l][0:3] == colorClass1:
					P+=1
				if pixSegment[k,l][0:3] == colorClass2:
					N+=1

		#calculate TP and TN (пиксели классифиц. как объект и явл. им)
		for k in range(0, w):
			for l in range(0, h):
				if pixLabel[k,l][0:3] == colorClass1 and pixSegment[k,l][0:3] == colorClass1:
					TP+=1
				if pixLabel[k,l][0:3] == colorClass2 and pixSegment[k,l][0:3] == colorClass2:
					TN+=1

		TP_g 	+= TP 
		TN_g 	+= TN
		P_g 	+= P
		N_g 	+= N

		#calculate accuracy for current image
		currentAcc = float(TP+TN) / float(P+N)

		resultArr.append(str(i)+' accuracy = '+str(currentAcc))
		print str(i)+' accuracy = '+str(currentAcc)

	#calculate mean global accuracy
	mean = float(TP_g+TN_g)/float(P_g+N_g)

	print 'Mean accuracy = '+str(mean)
	resultArr.append('Mean accuracy = '+str(mean))

	#write result
	resultFile = open(resultFileName, 'w')
	for item in resultArr:
  	    resultFile.write("%s\n" % item)

main()

 

Share this post


Link to post
Share on other sites

Вроде все верно, да и по картинками похоже.

Верных пикселей фона и объекта много больше чем ошибочных.

Чистый фон еще может смещение давать, если там все тривиально, для чистоты эксперимента нужен реальный фон, который будет при работе программы, какой использован у вас я не знаю.

  • Like 1

Share this post


Link to post
Share on other sites

Программа будет работать с объектами сфотографированными на белом, сероватом фоне. На примере ниже исходное фото, ручная разметка, сегментированное фото. Точность для данного примера составляет 0.997627852057preview.jpg

Исходное фото было "доведено" искусственно до размера 480х360. Надеюсь это не сильно влияет на результат.

 

 

 

Share this post


Link to post
Share on other sites

Не, на расчет точности никак не влияет.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×