관리 메뉴

A seeker after truth

PyCon 2017 세션 <대선 TV토론 쪼개기(이홍주 님)> 필기(음성 데이터 추출, 분석) 본문

수업 필기/데이터분석캡스톤디자인

PyCon 2017 세션 <대선 TV토론 쪼개기(이홍주 님)> 필기(음성 데이터 추출, 분석)

dr.meteor 2020. 3. 24. 11:31

프로그램 정보: https://archive.pycon.kr/2017/program/156

 

2017 대선후보 TV토론 쪼개기 (Who Spoke When?)

이 발표는 일반적으로 알려진 통계 또는 클러스터링 알고리즘으로 대선후보 TV토론의 오디오 스트림을 후보자별로 나누는(Who Spoke When?) 과정을 다룹니다. 전체 과정은 Feature Extraction, Segmentation, 그리고 Clustering 의 세 단계로 나뉘며, 각각에서 이런 내용들을 다룹니다.1. Feature Extraction : 첫번째 단계에서 대선후보 TV토론 방송 음원을 음성인식(Speech Recognition) 또는

archive.pycon.kr

영상 링크: https://www.youtube.com/watch?v=8LpY4KfYqbg&list=PLZPhyNeJvHRmvCnWMBZJiFXu9kDUcn5FG&index=41

 

 

1. speaker diarization

이 용어는 국내에 번역된 바가 없음. 그래서 논문 검색할 때 엄청 중요한 용어. 이 용어를 쳐야지만 내가 찾고자 하는 내용을 찾을 수 있을 거다.

VER? 이게 10%가 넘는다...

머신러닝 등이 나오면서 이제 다른 알고리즘에 의한 퍼포먼스가 매우 좋아짐

학계에선 아직도 해결이 안된 문제.

 

2. time domain VS frequency domain

시그널이 왼쪽에서처럼 시그널 1,2가 섞여 시간에 따른 amplitude면 녹색선이 된다. 근데 time d~였던 이 녹색을 fre~로 틀어버리는 것이 5페이지. 그러면 녹색선에 대한 amplitude만 있었던게 각 시그널에 대해 선분이 나오고, 그 시그널 주파수에 대해 amplitude도 나온다.

결론: 우리는 후자의 방법을 쓸 것이고, 이때 쓰는게 뭐시기 트랜스폼...7쪽에 해당하는 내용.

8쪽 슬라이드 왼쪽 맨 상단 그래프는 그냥 amplitude, 그리고 librosa란 라이브러리를 이용해 푸리에 변환한 뒤 파워 스펙트럼을 그렸다. 스펙트로그램은 저음역대가 압축된 형태로 보인다. 그래서 고음역대 위로 주파수가 올라갈수록 넓게 퍼진 형태를 보여주게 된다. 근데 사람의 귀는 주파수를 linear하게 인식하지 않는다. 그래서 고음역 주파수를 낮은 주파수 떼고 scaling?하는게 필요하고, 여기서 나오는 개념이 mel-scale이란 개념. 그래서 왼쪽 중간에 있는 그래프를 mel-scale 하면 고음역대에 있던 것이 저음역대로 내려오면서, 사람의 가청 주파수라고 하는 8000헤르츠 이하에 대해 고르게 분포하게 된다. 그래서 메일 스펙트럼을 그리게 되면 9쪽에 해당하는 그림 탄생

 

3. 특징 추출 (7쪽)

여기서 라플라스/푸리에 변환 써먹. 이렇게 변환된 것을 프레임이라고 하는데, 보통 25bs~30ms 단위로 쪼갠다. 그담에 10ms정도 오버래핑되는 프레임으로 움직이면서 이를 푸리에 변환을 하고, 주파수 도메인이 나온 것에 대해서 파워 스펙트럼을 만든다. this is 스펙트로그램. 여기서 특징 벡터 추출.

 

4. 9쪽 chromagram

8쪽 맨 아래 그래프에서 두 가지 방법으로 오디오 신화를 피처화하는게 가장 유명. 하나는 크로마그램, 다른 하나는 MFCC(mel frequency cepstral coefficients). 그 중 크로마그램은 12음계로 쪼개서 피치에 해당하는 것을 음계로 표시하여 피처를 만든 것이라 보면 된다.

 

5. MFCC 10쪽

실제 주파수 중에서도 실제 사람이 듣는 소리와 연관된 채널의 특성을 가장 잘 나타내는 10개에서 20개 정도이ㅡ 채널을 뽑아낸 것. 이 역시 스케일링을 좀 해야. 그래서 10쪽처럼 MFCC 뽑아낸 뒤 시각화할 땐 스케일들을 편게 아래 그림. 이를 10개 채널로 뽑아내고 1~10번이 분포하는 모습을 나타냄. 다중으로 채널이 어떤 것은 여러 개의 채널 signal의 amplitude가 있고, 어떤 채널엔 맨 밑의 것 하나만 나타나는 특성을 가짐.

 

6. Segmentation

11쪽은 웨이브폼 형태에서 크로마그램을 그려서 음계가 보여지게 된 것. 이걸 그냥 등분을 할 것이다. evenly-divined segmentation을 해서, 2~5초 간격으로 프레임을 만들어서 확대해서 보인 것이 맨 밑 맨 왼쪽. 여기서 보면 음계가 b에만 있는게 아니고 b플랫에도 조금 있다. a, a플랫도 있고... => 정확한 음역만 나온게 아니기 때문에 y축에 대해 amplitude가 가장 강한 애들만 뽑아내서 만든 게 가운데 그림. 이를 히스토그램화 한 것이 맨 오른쪽. counterization?을 해서 피처화한 것

13: 그럼 윈도우를 옮겨가면서 끝까지 하면, 12 음계에 대한 각각의 프레임?프라임?에 대한 벡터가 나온다. -> 12*12 매트릭스 만들 수 있음 이제 등분할된 세그멘테이션을 했고, 투표에서 피처 매트릭스를 만들었다.

피처 매트릭스를 만들어서 k 평균 클러스터링한 것이 14쪽.여기서 k=2인데, 2개의 클러스터로 점들을 클러스터링 한다면, 임의로 랜덤하게 센트로이드 포인트를 지정하고, 그 센트로이드에서 가까운 점들로 묶어서 (두번쨰 그림: 이쪽 점들은 왼쪽에 가깝고 오른쪽은 그 반대), 세번째 그림에서 이 두 클러스터들만의 중심으로 센트로이드를 다시 설정하고, 각 점들과 센트로이드의 거리들을 계산해서,또다시 가까운애들끼리 클러스터링하고(4번쨰..?) 이 과정을 계속 루프를 돌면서 센트로이드가 일정 slashhold...? flashhold...?로 움직일 때까지 본다.

 

그 두 명의 프레임이 나뉘어진 것이 15쪽. 그리곤 프레임을 시간순으로 재생.

근데 이런 방법은 좋은 방법이 아니다.단지 이해하기 쉽고 와닿기 떄문에 만든 예제일 뿐. 그래프 중간에 있는 애들애 에러를 내기도 한다. 그리고 심상정 후보는 여성이지만 피치가 낮아 이 클러스터링 방법에선 남성 후보의 목소리와 구분이 잘 안된다. 따라서 좋은 피처라이징 방법이 아니다. 그리고 목소리가 섞일 수 있다. 2초~5초 단위로 했지만 1초 안에서도 매우 많은 말을 할 수도 있다. 그래서 생각보다 긴 시간이다-2명이 이야기하기도 충분하다. 그러면 2초로 나눴을 떄 목소리 큰 사람이 이기겠죠. 왜냐면 아까 우리가 증폭(amplitude)을 갖고 max ~ 로 피처를 만들었기 때문. 근데 만약 전반 1초와 후반 1초에 각각 다른 사람이 이야기했다면 이것 역시 좀더 센 사람 쪽으로 세그먼트가 가서 붙겠지만, 결국 나중에 틀어보면 두 사람의 목소리가 섞여있을 것. 정확히 1초 1초 심상정, 유승민이라고 구분해주지 못한다.

 

16: 그래서 MFCC를 갖고 가변적 세그멘테이션을 할 것. 지금까지는 크로마~에 대해 등분할된 세그먼트에다가 k-means를 적용했지만, 이젠 mfccc로 특징 벡터를 만들고 가변적 세그멘테이션을 해서 계층 클러스터링을 할 것. 이 가변적 세그멘테이션은 발화자와 발화자 사이에 변환되는 점을 찾는 것이 중요하다.

 

17: 그래서 어떻게 할것인가, 가우스 믹스처 모델이란 것이 나오는데, 두 사람의 목소리를 mfcc로 변환을 해서 mfcc에 가우시안분포를 그려보면 서로 가우시안 모델이 다르다. 평균과 분산이 다르다. 그런데 왼쪽에서 오른쪽으로 프레임이 지나가면서 보면, 왼쪽 벡터는 파란색 그래프를, 오른쪽 벡터는 노란 그림을 따르는 지점이 있을 것이다. 그 지점이 바로 스피커가 바뀌는 지점이 될 것. 우린 그것을 찾을 것이다. 이걸 어떻게 찾느냐, 할 떄 나오는 것이

 

18: 베이지안 정보 기준이다. 모델에서 모델 셀렉션할 때 사용하는 것인데, 모델과 샘플 데이터가 있을 떄, 주어진 모델에서 새로운 관찰이 들어왔을 떄 이게 이 모델에서 발견될 확률에 대해...(그뒤로 설명 바뀜)

반면 어떤 샘플 데이터가 있는데 기존에 가지고 있던 모델에 대해 이게 핏 되느냐 안되느냐(가능성)를 갖고 이 모델이 이 데이터에 적당하느냐를 평가하는 코스트 함수...?역할을 한다. 그래서 밑의 수식 설명하면

x란 데이터에 대해 특정 모델에 대해 얼마나 적합한지를 로그 가능성을 계산하고, #M은 모델의 파라미터 계수?다. 선형 회귀를 해서 차원수를 많이 늘리면 오버핏팅된다고 하잖아요. 차원수가 많아지면 무조건 모델에 대한 function이 좋아진다.그래서 이를 Penalize할 필요가 있다. 차원수하고 샘플 배수와의 상관관계를 갖고 개수?계수?를 곱해서 빼주면 오버 피팅에 대해 penalize된 BIC가 나온다.

 

19: 이것도 마찬가지로 윈도우를 만들 것이다. 이것도 2~5초 정도로 논문에서 정의를 하는데 왼쪽 1초, 오른쪽 1초 이렇게 했다고 보면 윈도우를 왼쪽에서 오른쪽으로 움직이면서 왼쪽 윈도우와 오른쪽 윈도우가 서로 두 개의 모델로 모델링했을 때 더 BIC 계수가 좋은지, 혹은 하나의 모델로 BIC를 계산했을 때 더 스코어가 좋은지 이걸 판단할 것이다. 그래서 여기서 하나 더 나오는 개념이 generalized likelihood ratio란게 있다. null hypercess...???를 두 개의 윈도우가 만약 하나의 스피커라면 두 윈도우는 하나의 모델로 대변?이 될 것이다. 하는 비무가설을 하나 만들고, alternative hypercess???로 두 세그먼트가 서로 다른 스피커일 경우에 각각의 모델은 서로 다른 모델로 모델링되는게 더 자연스러울 것이다. 해서 두개로 나눈다. ratio로 나눈다. 그래서 대리베이션????뭐라는거지 을 하게되면 

 

20: 이런 수식이 나온다. H0와 H1에 대한 가설을 generalized likelihood ratio로 표시를 해서 대리베이션???한 수식이 이것. 복잡하지만 왼쪽 윈도우의 샘플 개수인 n1, 반대인 n2, 윈도우의 전체 샘플 데이터, 윈도우의 시그마, 왼쪽 윈도우의 시그마와 샘플 데이터를 빼고 오른쪽 윈도우의 시그마와 샘플 개수를 빼고 penalize를 해주면 델타 BIC 가 구해진다.

구현 코드는30쪽

 

21: s는 윈도우에 대해 covariance matrix...???를 구한 것, 여기에 determinent? 씌워서 로그값 구하면 저런 수식이 나온다. 그래서 이 수식을 갖고 윈도우를 돌리는 것.->31쪽

 

22: 왼->오로 윈도우를 돌리다보면 BIC가 최대화되는 부분이 있다. 여기가 바로 모델이 2개로 나뉘어지는 부분. 그래서 이 지점을 찾으면 스피커가 체인지되는 부분을 알 수가 있게 된다. 이 BIC는 특별할 때 쓸 것 같지만 그렇지 않음.

 

23: 클러스터링을 할 때 몇 개의 클러스터로 나눠야 할 것인가 하는 문제가 있는데, 이 문제를 해결할 떄도 BIC가 유용하게 활용된다.

 

24: 맨 마지막줄 range_n_clusters라고 2개에서 6개로 클러스터링을 쭉 해보고 이 클러스터에 대해서 믹스처 모델이 나올 건데, 23쪽 보면 대략 4개의 클러스터가 나오지 않는가. 이 4개의 mean과 분산을 받는 그런 믹스처 모델이 나올 것. 그럼 믹스처 모델을 만들고 이에 대해 BIC를 구했을 때 보면

 

25: 위 왼쪽부터 오른쪽까지 2~6개로 클러스터링한 것들. 맨 오른쪽 그래프는 BIC값을 0~1 사이 값을 min/max 스케일링을 한 것이다. 4개로 클러스터링을 했을 때 BIC값이 가장 작다. 그럼 이 데이터는 오른쪽 상단에 나와있는 것처럼 클러스터링을 하는게 맞다.. 이렇게 사용하는게 맞다는 판단을 할 수가 있게 되는 것. 이럴 때 사용하는게 모델 셀렉션을 하기위한 "아 이건 4개짜리 클러스터 모델이 잘 어울리는구나" 이렇게 활용할 수가 있는 것. 원랜 엘보(elbow???) 메서드란 것 많이 씀. 중심값에 대해서 variance 에서 sum of square...?하는...? 이게 드롭되는 ratio가 줄어들면 딱 거기를 쓰거나 실루엣 co-efficient 같은거 쓰는데 이 같은 경우는 컴퓨테이션 파워가 많이들어간다. 그래서 샘플링을 해ㅇ야하는게 있는데 이를 BIC 로 하게되면 훨 빠르고 간단하게 할 수 있게 된다.

 

26: 마지막으로 계층 클러스터링. k 평균법하고 비교해서 설명하면 k가 몇개의 클러스터링으로 해야하는지 미리 정의를 해줘야함. 또한 센트로이드에 대한 initial guess??가 매우 중요하다. 이것도 여러 가지 알고리즘으로 guessing을 하는게 이것에 대해 서로 결과가 달라진다. 또한 어떤 두 점이 있으면 그걸 유클라디언 거리로 계산할 건지 다른 방법으로 계산할건지에 대한 거리 측정이 필요하게 된다.

하지만 계층 클러스터링은 우리가 몇개로 클러스터링을 해야하는지 정의할 필요가 없다. 이니셜 게스도 필요 없음. 단지 penalizing distance...???가 서로 다른 두 개의 데이터 포인트가 얼마나 서로 유사한지에 대한 정의만 해주면 됨

 

27: 그래서 전체 데이터를 쪼개면서 이진 트리를 구하는게 devicive method...???라고 하고, 모든 데이터 포인트를 한개의 클러스터로 가정한 다음 이것들을 뭉쳐서 전체가 하나가 될 때까지 이진 트리를 구하는 것을 agglomerative 클러스터링(=군집화)이라 한다. bottom of approach. 전체 각각의 데이터 포인트를 한개의 클러스터로 보고 iteration...????을 보는데 제일 가까운 페어를 찾아내서 merge를 하고 이 merge한 것을 또 다른 클러스터로 정리를 하고 또 전체에서 제일 가까운 클러스터를 또 merge하고  이걸 계속 반복. 그래서 모든 데이터 포인트가 하나의 클러스터가 될 떄까지 반복하거나 define된 거리가 define된 slashhold???를 초과할 때까지 iteration을 도는 것. 뒷부분부터는 예제

 

28: 11개의 데이터포인트가 있는데 숫자는 11개의 데이터 포인트의 인덱스를 말함. 대충 4개 정도의 군집이 있는 걸 볼 수 있음.

 

29: 계층 클러스터링을 위한 함수 사용. pdistance는 각각의, 0~11과 0~11의 매트릭스를 구해서 씨매트리컬한 거리 매트릭스를 그려준다. 이게 페어 와이즈드??? 거리. 그래서 가운데 크로스라인은 거리가 0인 것. 참고로 유클리디언 거리. 이 매트릭스에 대해 스퀘어폼으로 출력해주면 이런 형식으로 나오게 되고,

 

30: linkage: 클러스터 간의 거리를 정의할 때 각 클러스터읱 중심점 간 거리를 할건지, 혹은 그 두 클러스터의 제일 가까운 포인트의 거리를 계산할건지 혹은 두 클러스터의 제일 먼 포인트를 계산할건지 이런걸 single(default설정)/avg/coupling linkage. 디폴트인 아이의 경우 두 클러스터가 있었을 때 젤 가까운 점들의 거리를 계산. 30쪽 자료는 요것에 해당. 대신 보는 방법이 조금 복잡.

이게 7번과 8번 데이터 포인트의 거리가 0.3이고 하나의 클러스터가 만들어지는데 이게 11번 클러스터가 된다. 거기엔 2개의 데이터 포인트(지금 array의 첫번째 줄의 4차원 벡터 1~4번쨰 원소 차례대로 설명해주는 거) 7,8번이 들어가게 된다. 2번째 array 데이터는 12번 클러스터라고 함. 그럼 3번째 벡터 4번째 원소가 3인 이유? 1, 10, 3번이 하나의 클러스터?로 머지가 되기 때문. 그래서 12번은 3개가 되고... 이런 식으로 19번 클러스터까지 나오게 되고, 이를

 

31: 덴드로그램으로 그리면 이렇게 되는 것. 얜 녹색, 빨간색, 파란색(5번 클러스터 하나밖에 없겠지만 그래도) 이렇게 3개로 나누면 되겠더라고 판단까지 해주지만

 

32: 이 그래프는 3개로 끊은 거고, 오른쪽 그래프에서 1.00 조금 아래서 끊었으면 4개로 클러스터링 되었을 것. 근데 여기서 우리가 클러스터를 3개로 쪼개는 이유는 5번 클러스터의 거리가 대충 1.4(y축에 매핑해보면 됨) 정도 되는데 이게 다른 애들의 거리보다 더 길기  때문에 3개 쯤에서 클러스터링을 멈춰야겠다 라고 해서 여길 끊게 되는 것. 그래서 덴드로그램으로 그려보면 클러스터를 몇 개로 나누어야 하는지에 대한 내추럴 클러스터하는 분석 도구가 되는 것. 그리고 또 하나는 아웃라이어 발견을 할 수 있게 되는 건데, 거리를 보면 다들 1.2이하의 거리를 갖고 있지만 5번 혼자서만 1.5가까이 되는 거리값을 갖고 있음. 게다가 클러스터안에 자기 혼자만 포함되어 잇따. 그럼 이게 클러스터링하는데 어떻게 사용되냐,

 

33: 각 세그먼트들은 동일한 목소리의 클러스터라고 보고, changing point들이기 때문에 이웃하지 않는 세그먼트 중에선 같은 사람 목소리일 수가 있. 그럼 이걸 bottom-up 클러스터링을 해서 같은 사람들끼리 묶어줄 것

 

34: 그 방법으로는 이 자료 나온 것처럼 같은 색깔끼린 같은 사람이라고 가정하자. 그럼 클러스터 2&3(서로 다른 목소리)의 BIC보다  클러스터 2&4의 BIC가 작을 것. 그럼 같은 모델이냐 다른 모델이냐? 이 차이로 BIC 값이 대소가 나온다.

 

35: 이를 순서로 나눠서  sorting해가지고 segment*segment의 BIC 매트릭스를 구한 다음(그게 왼쪽 그림) 제일 작은 값을 뽑아서 2,4번이 젤 작아서 하나로 묶고(7번 클러스터에 해당. 오른쪽 덴드로그램 보면 알 수 있음), 이를 업데이트를 하고. 업데이트 된 것 중 제일 작은게 7&6 조합. 다음 3&5... 이런 식으로 클러스터링 가능. 전체가 하나가 될 때까지, 클러스터링 11번까지 만들 수도 있지만 우린 이제 BIC 가 슬래시홀드0값보다 작을 때까지만 하면 된다. 여기서 딱 멈춰주면 아, 스피커가 3명이다. C1,8,9이 그 3명. 이란걸 알수 잇.

 

36:

기쁘게도 librosa는 스피치보다 음악쪽에 더 많이 쓰이는 라이브러리.

그리고 크로마그래피 세그멘테이션 한건 머신러닝&텐서플로 책 참고했다는데, 텐서플로로 구현하면 잘 안들어간다고 함. 여기 나온 예제가 별로라 함.

그리고 3번째에 나온 논문의 참고 논문 안에 speaker diarization에 대한 메서드를 총망라했다고 함.

맨마지막 논문은 처음으로 BIC 를 여기에 활용해서 좋은 퍼포먼스를 낼 수 있다는 소개가 된 논문.