Перейти к содержимому
Compvision.ru
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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
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 - это кол-во файлов?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

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

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

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

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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()

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

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

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×