본문 바로가기
Programming/Computer Vision

ValueError: matrix contains invalid numeric entries 에러 억제 방법 (Yolov5 + deepSORT)

by a voyager 2021. 10. 26.
728x90
반응형

 

증상

 

Yolov5 + deepSORT object tracking 알고리즘 실행 시 다음과 같은 에러를 만났다. 어떤 matrix에 숫자로 타당하지 않은 원소가 있다는 에러이다.

 

return _lsap_module.calculate_assignment(cost_matrix)
ValueError: matrix contains invalid numeric entries

 

이 에러는 linear_assignment.py 파일안에 있는 scipy.optimize.linear_sum_assignment()에 의해 계산된 cost_matrix에 nan (Not a Number)이 포함되어 있어 발생하는 에러이다.

 

아래와 같이 프로그램을 다시 돌려 cost_matrix가 어떤 값을 가지는지 확인해보자.

 

역시 NaN이 들어있는 것을 알 수 있다.  이것은 주로 어떤 수를 0으로 나누었을 때 발생하는 data type이며, 예외 처리를 못하고 에러가 나게 된 것으로 보인다. 

 

 

github 커뮤니티 논의 - Scipy 버그 

 

이 에러에 대한 논의는 다음의 링크에서도 찾아볼 수 있다. 

linear_sum_assignment with infinite weights #6900

 

위 링크속 논의에 의하면 linear_sum_assignment()는 scipy의 method인데, 이 코드에 버그가 있다는 것이다. 

 

 

다음의 간단한 예를 통해 똑같은 에러를 일으켜 볼 수 있다.  

 

inf의 원소를 가지는 costSet1NaN이 들어 있는 costSet2를 만든다. 

 

import numpy as np 
import scipy

costSet1 = np.array(
    [[np.inf, 1, np.inf], 
    [np.inf, 3, np.inf], 
    [2, np.inf, 3]])


costSet2 = np.array(
    [[np.nan, 1, np.nan], 
    [np.nan, 3, np.nan], 
    [2, np.nan, 3]])


print(f'costSet1: \n {costSet1}')
print("")
print(f'costSet2: \n {costSet2}')

 

 

  • costSet1: cost matrix is infeasible 
scipy.optimize.linear_sum_assignment(cost_matrix=costSet1)

 

  • costSet2: matrix contains invalid numeric entries
scipy.optimize.linear_sum_assignment(cost_matrix=costSet2)

 

costSet2에서 볼 수 있듯이 NaN이 원래 문제와 같은 에러를 낸다. 

 

 

해결 방법 

 

이것이 진짜 버그인지 알 수 없지만 예외처리가 안되어 생긴 문제인 것은 분명하기 때문에, linear_assignment.py내의 함수를 수정하여 에러가 나지 않도록 처리를 하는 것이 좋겠다. 

 

즉, NaN을 임의의 아주 큰 값 (INFTY_COST=1e5) 으로 대체하는 것이다. 

 

다음의 코드는  linear_assignment.py의 한 부분이며 linear_sum_assignment_with_inf라는 함수를 만들어 cost_matrix에서 발생하는 예외를 처리해 주었다. 

 

INFTY_COST = 1e+5

def linear_sum_assignment_with_inf(cost_matrix):
    cost_matrix = np.asarray(cost_matrix)
    nan = np.isnan(cost_matrix).any()
    if nan:
        cost_matrix[np.isnan(cost_matrix)]=INFTY_COST

    return linear_assignment(cost_matrix)


def min_cost_matching(
        distance_metric, max_distance, tracks, detections, track_indices=None,
        detection_indices=None):
    """Solve linear assignment problem.
    
    .
    .
    .
    
    cost_matrix = distance_metric(
        tracks, detections, track_indices, detection_indices)
    cost_matrix[cost_matrix > max_distance] = max_distance + 1e-5
    
	row_indices, col_indices = linear_sum_assignment_with_inf(cost_matrix)

	.
    .
    .

 

이렇게 처리하면 일단 에러가 나서 프로그램이 중단하는 것은 막을 수 있다. 

 

 

 

 

728x90
반응형

댓글