본문 바로가기

Translation/Article_translation

[Connectionist Temporal Classification]번역 글

반응형

CRNN모델에서 마지막에 loss를 계산할 때

ctc_loss를 사용하기 때문에 CTC 관련해서 어느 정도 알고 있어야 함

 

아래 내용은 위의 링크의 Medium에서 작성 된 글을 번역 한 글입니다. 

An Intuitive Explanation of Connectionist Temporal Classification

 

https://towardsdatascience.com/intuitively-understanding-connectionist-temporal-classification-3797e43a86c

 

An Intuitive Explanation of Connectionist Temporal Classification

Text recognition with the Connectionist Temporal Classification (CTC) loss and decoding operation

towardsdatascience.com

 

만약 당신이 텍스트를 인식하는 컴퓨터를 필요로 한다면, 뉴럴 네트워크는 지금 시점에서 다른 접근법들보다 뛰어나기 때문에 최선의 선택이라고 볼 수 있다. 그러한 용도로 사용되는 뉴럴 네트워크는 주로 피처 시퀀스를 추출하는 CRNN과 시퀀스로부터 정보를 전파하는 RNN으로 구성되어 있다. 각각의 시퀀스 요소에 대한 문자의 점수를 출력하며, 그 값들은 행렬로 표현된다. 이제, 이 매트릭스를 이용해 우리가 하고 싶은 것은 두 가지가 있다.

 

1. TRAIN : 뉴럴 네트워크에 훈련시키기 위해 로스 값을 계산

2. INFER : 인풋 이미지에 포함된 텍스트를 얻기 위해 행렬을 디코드

 

위의 2가지가 CTC operation에 의해 이루어졌다. 손글씨 인식 시스템에 대한 개요는 Fig.1에서 확인할 수 있다.

 

이제 CTC operation에 대해 더 자세히 살펴보고 복잡한 수식을 기반으로 하는 아이디어를 숨기지 않고 어떻게 작동하는지에 대해 논의한다. 그리고 마지막에는 관심이 있다면 참고할 수 있는 Python코드와 복잡하지 않은 수식들을 참고할 수 있는 곳을 알려줄 것이다.

 

Why we want to use CTC

당연히 우리는 text-lines의 이미지가 있는 데이터셋을 생성한다 그리고 각 이미지의 수평 위치에 대해 일치하는 문자를 지정한다(Fig에서 볼 수 있다). 그다음에, 우리는 각각의 수평적인 위치에 문자 점수를 출력하도록 뉴럴 네트워크를 학습시킬 수 있다. 하지만 이 간단한 해결에는 2가지의 문제가 있다. 

 

1. 문자 단계의 데이터 셋에 어노테이션을 생성하는 것은 시간이 많이 걸리고 지루하다.

2. 우리는 문자 단위 점수만 얻기 때문에, 그것으로 부터 최종 텍스트를 얻기 위해서는 몇몇의 추가적인 과정이 필요로 한다. 하나의 문자는 여러 개의 수평 위치에 걸쳐져 있을 수 있다. 예를 들면 'o'는 넓은 문자이기 때문에 우리는 'ttooo'를 얻게 될 수 있다. 그래서 우리는 모든 중복된 't'와 'o'를 제거해야 한다.  그러나 원래의 텍스트가 'too' 일 때, 우리가 모든 중복된 'o'를 제거하면 우리는 잘못된 결과를 얻게 된다. 이럴 경우 어떻게 처리할까?

 

 

CTC는 우리를 위해 위의 2가지의 문제점을 해결해준다. 

 

1. 우리는 우리는 이미지에서 발생된 텍스트의 CTC loss function에 대해만 언급해야 한다. 

   그러므로 우리는 이미지 속의 위치와 문자의 넓이는 무시한다.

2. 인식된 텍스트에 대해서 추가적인 처리가 필요하지 않다.

 

How CTC works

앞서 언급했듯이, 우리는 각각의 수평적인 위치의 이미지를 어노테이션 하는 것을 원하지 않는다 ( 우리는 지금부터 이러한 과정을 time-step이라고 부를 것이다). 뉴럴 네트워크 학습은 CTC loss function에 의해 지도될 것이다.

 

오직 뉴럴 네트워크의 아웃풋 행렬 그리고 일치하는 ground-truth(GT) 텍스트만을 CTC loss function에 제공한다.

 

그러나 어디서 각각의 문자가 발생되는지 어떻게 알 수 있을까? 그것은 알 수 없다. 대신 이미지에서의 GT 텍스트의 모든 가능한 정렬(조정)을 시도하고 모든 점수의 합계를 취한다. 이렇게 하면 각 정렬의 합계가 높은 값을 가지면 GT텍스트의 점수도 높은 값을 가진다.

 

Encoding the text 

중복된 문자를 어떻게 인코드 하는 가에 대한 이슈가 있었다. 그 이슈는 pseudo-character가 소개되면서 해결되었다(blank라고 불린다. 그러나 실제의 공백과 혼동하면 안 된다). 이러한 특별한 문자는 다음의 텍스트에서 '-'로 표시되어질 것이다. 우리는 중복 문자 문제를 해결하기 위해 영리한 코딩 스키마를 사용한다. 텍스트를 인코딩할 때, 어떤 위치에든 임의의 많은 blank들을 넣을 수 있다. 그리고 그 blank들은 디코딩할 때 제거될 것이다. 그러나 우리는 중복된 문자 사이에 blank를 넣어야 한다. 추가로 우리는 원하는 만큼 각각의 문자를 반복할 수 있다. 

 

아래의 예제를 확인한다 :

위에서 확인할 수 있듯이, 이 스키마는 쉽게 같은 텍스트의 다른 정렬을 쉽게 생성하도록 한다. 예를 들면 't-o'와 'too' 그리고 '-to'는 모두 같은 텍스트('to')를 나타내지만 이미지에는 다른 정렬을 가진다. 그 뉴럴 네트워크는 인코딩 된 텍스를 출력하도록 훈련된다. 

 

Loss calculation

우리는 뉴럴 네트워크에 훈련시키기 위해 주어진 이미지와 GT텍스트의 쌍에 대한 loss 값을 계산할 필요가 있다. 너는 뉴럴 네트워크가 매 타입 스텝에 각각의 문자의 점수를 포함하는 행렬을 출력한다는 것을 알고 있다. 최소한의 행렬은 Fig3에서 확인할 수 있다 : 거기에는 두 번의 타입 스텝(t0, t1)과 3개의 문자('a', 'b', '-') 들이 존재한다. 매 타입 스텝에서의 문자 점수들의 합은 1이다.

 

게다가, 당신은 이미 손실 값은 GT 텍스트의 모든 정렬 가능한 점수가 합해짐으로써 계산되었다는 것을 알고 있다. 이 방법은 텍스트가 이미지에 나타나는 위치는 전혀 중요하지 않다.

 

하나의 길에 대한 점수는 그 길에 일치하는 문자 점수들의 곱으로 계산된다. 위에 보이는 그림으로 예시를 들면 'aa'라는 길에 대한 점수는 0.4 * 0.4 = 1.6이다. 그 반면에 '-a'에 대한 점수는 0.6 * 0.4 = 0.24, 'a-'에 대한 점수는 0.4 * 0.6 = 2.4이다. 주어진 GT 문자에 대한 점수를 구하기 위해서는, 우리는 이 문자와 일치하는 모든 길에 대한 점수를 합해야 한다.

이제 GT문자가 'a'라고 가정한다 : 우리는 길이가 2인 모든 가능한 길에 대해 점수를 계산해야 한다. 모든 가능한 길은 'aa'와 '-a' 그리고 'a-'가 있다. 우리는 이미 이러한 길들에 대한 점수를 계산해 놓았다. 그래서 우리가 단지 이것들을 합하면 0.4*0.4 + 0.4*0.6 + 0.6*0.4 = 0.64라는 값을 얻을 수 있다. 만약에 GT 텍스트가 ''라고 가정한다면 , 우리는 오직 하나의 일치하는 길을 볼 수 있다(그 길은 '--'이다). 그리고 그 길의 점수는 0.6*0.6=0.36이다.

 

만약 당신이 자세히 들여다본다. 우리가 손실 값이 아닌 GT텍스트의 가능성을 계산하고 있다는 사실을 알 수 있다. 그러나 손실 값은 단순히 이 가능성에 음의 로그 값을 취한 것이다.  그 손실 값은 뉴럴 네트워크를 통해 역전파가 이뤄지고, 그 뉴럴 네트워크의 파라미터 값들이 사용된 옵티마이저에 따라 새롭게 갱신이 된다.

 

 

Decoding

우리가 뉴럴 네트워크를 훈련시킬 때, 우리는 보통 이전에 보지 못한 이미지에 있는 텍스트를 인지 하기 위해 이것을 사용한다. 또는 더 기술적인 용어로 : 우리는 뉴럴 네트워크의 출력 행렬에서 가장 가능성이 높은 텍스트를 계산하려고 한다. 너는 이미 주어진 문자의 점수를 계산하는 방법을 알고 있다. 그러나 이번에 우리는 어떠한 문자열도 입력하지 않았다. 실제로 이 텍스트는 우리가 찾는 텍스트이다. 몇몇의 타임 스텝과 문자들만 있으면 가능한 모든 텍스트를 시도하지만, 실용적인 경우에는 가능하지 않다.

 

단순하고 가장 빠른 알고리즘은 두 단계로 구성된 best path decoding이다.

 

1. 타임 스텝마다 가장 가능성이 높은 문자를 채택함으로써 최고의 길을 계산한다

2. 중복 문자를 먼저 제거하면서 인코딩을 하지 않는다. 그리고 그 길에 있는 모든 blank를 지운다. 그리고 남아있는 문자는 인식된 텍스트임을 나타낸다. 

 

Fig4에서 예제를 볼 수 있다. 문자는 'a', 'b' 그리고'-'(blank)로 구성되어있다. 그리고 5번의 타임 스텝이 있다. 이 행렬의 우리의 최고의 길을 찾는 디코더를 적용한다 : t0에서 가장 가능성이 높은 문자는 'a'이다. 같은 방식으로 t1과 t2도 적용된다. t3에서는 blank가 가장 높은 점수를 갖는다. 마지막으로 t4에서는 'b'가 가장 가능성이 높다. 이것은 우리에게 'aaa-b'라는 경로를 준다. 그리고 우리는 중복된 문자를 제거한다. 그러면 'a-b'가 남는다. 그리고 우리는 남아있는 경로에서 blank를 제거한다. 그러면 인식된 텍스트로써 'ab'라는 결과를 출력한다.

 

 

물론, 최고의 디코딩 경로는 오직 근사치 결괏값이다. 그것은 잘못된 결과를 주는 예제를 구성할 수 있다. 만약에 Fig3에서 행렬을 디코드 했다면 너는 ''를 인식된 결과로 얻을 것이다. 그러나 우리는 ''는 'a'가 0.64인 반면에 오직 0.36의 가능성이라는 것을 알고 있다. 그러나 그 대략의 알고리즘은 종종 실용적인 상황에서 좋은 결과를 주곤 한다. 

 

그리고 빔 검색 디코더, 접두사 검색 디코딩 또는 토큰 전달과 같은 고급 디코더가 더 있으며, 결과를 향상하기 위해 언어 구조에 대한 정보도 사용합니다.

 

Conclusion and further reading

첫 번째로, 우리는 뉴럴 네트워크와 함께 발생하는 문제에 대해 살펴보았다. 그다음에, 우리는 어떻게 CTC가 이러한 문제를 해결할 수 있는 방법을 확인했다. 그리고 CTC가 텍스트를 인코딩하는 방법, 어떻게 손실 계산이 수행되는지 그리고 어떻게 CTC에서 훈련된 뉴럴 네트워크의 출력이 디코딩되는지도 함께 살펴보았다.

 

이를 통해 너는 이러한 상황 뒤에서 어떤 일들이 일어났는지 잘 파악할 수 있게 될 것이다.  그러나 네가 CTC에 대해 더 향상하고 싶고 또 더  빨리 수행시키고 싶다면 너는 더 자세한 상황에 대해 알 필요가 있다. [1]은 CTC 작동에 대한 소개한다. 그 논문은 또한 모든 관련된 수학들에 대해서도 소개해준다. [2][3]은 당신이 어떻게 디코딩을 향상하는지에 대해 알고 싶다면, 빔 검색 디코딩에 대한 기사를 자세히 살펴보면 좋다. [4][5] 몇몇의 디코더와 손실 함수를 Python과 C++에서 구현했는데, 이는 깃허브에서 찾을 수 있다. [6] 마지막으로 만약에 어떻게 텍스트를 인지 하는지에 대해 더 큰 그림을 가지고 찾는다면 나의 다른 기사를 참고해보라. 이는 어떻게 손글씨 인식 시스템을 구현했는지에 대한 것이다.

 

[1] Original paper containing all the math
[2] Vanilla beam search decoding
[3] Word beam search decoding
[4] Python implementation of decoders
[5] Implementation of word beam search decoding
[6] Text recognition system

반응형