13장 텍스트 유사성
자연어 처리
- 빠른 텍스트 분석에 중점을 둔 데이터 과학의한 분야
- 일반적으로 대량의 텍스트 데이터셋에 적용되는 편
- 텍스트 간 유사점과 차이점을 분석하는 데 의존적이다.
텍스트 비교
- 텍스트 간 유사도를 비교하려면 텍스트 간 차이를 정량화 해야한다.
- 기본 접근법 : 각 텍스트 쌍에 공유되는 단어 수를 단순히 계산하는 것.
- 각 텍스트를 단어 단위로 분할하여 단어 리스트를 만들어야 한다.
- 토큰화 : 텍스트를 개별 단어로 분할하는 과정
정확한 단어를 비교하는 것이 불가능한 이유
- 일관성 없는 대문자
- 일관성 없는 구두점(특수문자 등)
합집합 : 텍스트 간 겹치는 단어와 겹치지 않는 단어를 모두 결합할 때 사용
두 텍스트의 유사성을 평가하는 간단한 지표의 작동 방식( 자카드 유사도 혹은 자카드 지수 )
- 두 텍스트가 주어졌을 때 각 텍스트에서 단어 리스트를 추출한다.
- 텍스트 간 공유되는 고유 단어 수를 센다
- 공유 단어 수를 두 텍스트의 총 고유 단어 수로 나눈다.
자카드 유사도는 전체 단어 수에 대한 교집합 비율과 같다.
자카드 유사도가 텍스트의 유사성을 합리적으로 측정하는 척도인 이유
- 텍스트 간 겹치는 단어와 겹치지 않는 단어를 함께 고려한다.
- 항상 0과 1 사이로 표현되며 해석이 쉽다. 0 = 공유 단어 없음. 0.5 = 절반의 단어가 공유됨. 1 = 모든 단어가 공유됨.
- 쉽게 구현할 수 있다.
단어를 숫자 값으로 바꾸기
→ 단어와 숫자 값 간의 매핑 정ㅇ보는 파이썬의 딕셔너리로 저장할 수 있으며, 정보를 담은 딕셔너리를 어휘라고 한다.
텍스트의 합집합에 있는 모든 단어에 번호를 매길 때 임의의 단어를 꺼내서 번호를 할당한다. 이 기법을 '단어 가방 기법'이라함.
벡터 : 1차원 숫자 배열을 수학적으로.
텍스트의 벡터화 : 텍스트를 벡터로 변환하는 과정
텍스트를 벡터화 하는 가장 간단한 방법
- 이진 요소로 구성된 벡터를 만드는 것
- 이 벡터의 각 인덱스는 어휘 내 한 단어에 연결됨
- 연결된 텍스트에서 일부 어휘 단어가 누락되더라도 벡터 크기는 어휘 크기와 같다.
- i 인덱스의 단어가 텍스트에서 누락된 경우 벡터의 i번째 오소는 0으로 설정되며 그렇지 않다면 1로 설정된다.
- 벡터 내 모든 단어에 대한 인덱스에는 0 또는 1값이 할당된다.
이진 벡터화로 모든 텍스트를 넘파이 배열로 변환.
시본 라이브러리를 활용해 테이블을 히트맵으로 시각화.
- 테이블을 이용해 어떤 단어가 어떤 텍스트 간 공유되는지 쉽게 알 수 있다.
- 이진 벡터 표현은 공유 단어를 숫자로 추출할 수 있게 해 준다.
내적 : 벡터의 요소별 곱을 모두 더하는 것
- 내적을 이용해 공유된 단어 수를 구할 수 있다.
- 교집합의 크기와 일치한다.
타니모토 유사도 : 벡터화된 텍스트로 자카드 유사도를 구현한 것
단어 수를 사용하여 텍스트 벡터화하기
두 텍스트가 있을 때 등장 횟수를 바탕으로 어떤 단어가 중요한지, 어떤 주장을 펼칠지 추측 가능하다.
용어 빈도 벡터(TF 벡터) : 단어 수 벡터
- 이진 값을 단어 수로 바꾸면 유사도 출력을 크게 바꿀 수 있다.
- TF 벡터화는 두 텍스트의 선호도를 더욱 뚜렷하게 만든다.
- TF 벡터는 텍스트 간 단어 수 차이에 민감하기 때문에 향상된 비교 결과를 제공한다.
- 길이가 다른 텍스트를 비교할 때는 불리할 수 있다 → 이를 정규화로 해결 가능하다..
정규화로 TF벡터 유사도 개선하기
- 검색 엔진에선 크기 신호가 잘못된 순위로 이어질 수 있다.
- 텍스트 크기가 순위 결과에 미치는 영향을 억제할 필요가 있다.
- 한 가지 간단한 접근법 : title_a_vector 를 3으로 나누는 것이다.
벡터를 선분으로 시각화하면?
- 각 선분들은 기하학적인 길이를 가짐.
- 모든 벡터가 기하학적인 길이를 가지며 이를 크기라고 함.
- 크기를 유클리드 노름 또는 L2 노름이라고 함.
단위 벡터 : 크기가 1인 벡터
장점 : 비교가 쉽다. 단위 벡터 간 차이는 방향에 따라서만 결정된다.
정규화 : 어떤 벡터든 자기 자신의 크기로 나누는 것
v / norm(v)를 사용해 크기가 1인 정규화된 벡터를 얻을 수 있다.
벡터 정규화는 타니모토 유사도를 더 효율적으로 개선시킬 수 있다.
두 벡터가 정규화되었다면 이들에 대한 타니모토 유사도는 유클리드 및 코사인 지표로 대체될 수 있다.
타니모토 유사도와 유클리드 및 코사인 지표 측정값이 정규화된 내적과 매우 밀접히 관련되어 있기 때문이다.
단위 벡터 내적으로 관련성 지표 간 변환하기
기하학적으로 두 단위 벡터의 내적은 두 벡터 간 각도에 대한 코사인과 같다.
코사인 유사도 : 두 단위 벡터의 내적
코사인 유사도를 cs라고 했을 때, (2-2*cs) ** 0.5 와 cs / (2-cs) 를 계산하여 유클리드 거리와 타니모토 유사도로 변환할 수 있다.
정규화된 벡터 간 타니모토 유사도는 다른 유사도 또는 거리 지표로 변환될 수 있다. 이 변환이 유용한 이유는
- 타니모토 유사도를 유클리드 거리로 변환 시 텍스트 데이터에 대한 K-평균 클러스터링을 수행할 수 있다.
- 타니모토 유사도를 코사인 유사도로 변환하면 계산을 간소화할 수 있다. 모든 계산이 간단한 내적 연산을로 축소된다.
정규화를 이용할 때 이점
- 텍스트 길이에 따른 차별성 제거
- 보다 효율적인 타니모토 유사도의 계산
- 모든 벡터 쌍들에 대한 보다 효율적인 유사도 계산
텍스트 간 유사도에 대한 테이블이 행렬 곱셈을 이용해 멋지게 계산될 수 있음!!
효율적인 유사도 계산을 위한 행렬 곱셈
어떤 텍스트 쌍이 가장 높은 유사도를 보이는지 즉시 알 수 있음.
중복된 연산을 행렬 곱셈을 이용해 제거하면 더 효율적임..
행렬 : 1차원 벡터를 2차원으로 확장한 것, 숫자를 테이블 형태로 표현한 것
행렬의 곱 : 벡터 내ㅐ적을 2차원으로 일반화한 것
전체 행렬에대한 유사도 계산하기
정규화된 단위 벡터와 그 단위벡터의 전치를 내적하면 단위 벡터스스로에 대한 코사인 유사도를 구할 수 있다. 물로 다 1로 채워짐...
이 코사인 값은 텍스트 사이의 단어 중복과 차이를 반영한 타니모토 값으로 변환될 수 있다.
타니모토 유사도 계산 일반화한 함수 구현
- 두 넘파이 배열을 입력받는다. 차원에 제한은 없다.
- 두 넘파이 배열에 @ 연산자를 적용한다. 두 배열이 행렬이라면 @ 연산자를 수행한 결과는 행렬 곱셈이 계산된 새로운 행렬을 반환한다.
- 산술 연산자로 행렬의 곱셈 결과를 수정한다. 산술 연산자는 숫자와 행렬 모두에 동일하게 적용될 수 있다.
행렬 곱셈의 계산 한계
행렬 곱셈의 계산 속도는 해애렬 크기에 따라 결정되므로 행렬이 커질수록 계산 시간도 매우 길어지게 된다.
그러므로, 어떻게든 실행 시간을 줄여야한다. 그 한 가지 접근법은 해ㅐㅇ렬 크기를 줄이는 것이다.
14 행렬 데이터의 차원 감소
차원 축소 : 데이터 정보 내용을 유지한 채 데이터를 축소하는 기술
차원 축소의 이점
- 압축된 데이터는 전송과 저장이 더 쉽습니다.
- 적은 데이터에 대한 알고리즘 수행 시간은 단축됩니다.
- 데이터 그룹/클러스터를 파악하는 등 복잡한 작업에서 불필요한 노이즈 정보를 제거하여 복잡함을 간소화할 수 있습니다.
2D 데이터를 단일 차원으로 그룹화하기
- 차원 축소는 클러스터링/그룹화를 보다 쉽게 해석하는 것을 포함해서 다양한 용도로 활용된다.
- 클러스터링은 중심성 또는 평균까지 거리처럼 기술 개념에 의존할 수 없다.
- 한 그림으로 설명할 수 있다면 가장 이상적일 것이다.
- 차원축소는 이러한 수준의 단순성을 달성할 수 있게 해준다.
- 맷플롯립은 2D 축을 자동으로 조작해 그래프를 미적으로 보기 좋게 만듭니다.
그룹/클러스터를 구하는 한 방법은 K-평균을 활용하는 것이다.
그 대신 그래프를 옆으로 기울이는 비교적 덜 기술적인 해결책도 있다.
그래프가 수평으로 배치되면 다음 그림과 같이 두 수직선으로 세 부분으로 분리할 수 있다.
회전으로 차원 줄이기
데이터를 뒤집으로면 두 가지 단계별로 실행되어야 한다.
- 좌표 (0,0)의 원점을 중심으로 모든 데이터를 이동시킨다. 그러면 X축 방향으로 더 쉽게 회전시킬 수 있다.
- 데이터에서 X축까지 총 거리가 최소화될 때까지 데이터를 회전한다.
원점에서 데이터의 중심을 잡는것은 간단하다. 모든 데이터셋의 중심점은 평균과 같기 때문이다.
따라서 좌표를 조정해 X 값의 평균 및 Y 값의 평균이 모두 0이 되도록 해야한다. 이는 데이터 좌표에서 현재 평균을 빼면 가능하다.
2D 그래프를 중심을 기준으로 회전하려면 회전 행렬을 사용해야한다
이 이동을 정량화할 방법이 필요하다. 이를 위해 데이터가 X축을 향해 회전함에 따라 감소하는 페널티 점수를 생성한다.
모든 Y축 값에 페널티를 적용한다. 페널티는 제곱 거리 개념을 기반으로 한다.
페널티 제곱은 rotated_data의 y값 제곱들 평균과 같다. y값은 x축까지 거리를 나타내므로, 페널티는 x축까지 평균 제곱 거리와 같다. 즉, 회전된 데이터셋이 x축에 가까워지면 평균 제곱 y값은 감소한다. 페널티를 잘 받게 되는 것이다.
데이터를 회전하면서 페널티 점수가 20배 이상 감소했다. 이 감소는 통계적 해석이 수반되며 다음을 고려하면 페널티 분산에 연관지을 수 있다.
- 페널티 점수는 0에서 y_value 배열 내 모든 y 까지 거리를 제곱한 평균과 같다.
- 페널티 제곱은 평균에서 y까지 거리를 제곱한 평균과 같다.
- 평균에서 거리를 제곱한 평균은 분산과 같다.
페널티 점수가 y축 분산과 같다고 추론했다. 결과적으로 데이터 회전으로 y축의 분산이 20뱁 이상 감소한 것이다.
분산을 기반으로 하여 회전 점수를 매길 수 있다. 데이터를 x축 방향으로 회전하면 y축의 분산은 감소할 것이다.
회전이 x축의 분산에는 어떤 영향을 미칠까?
회전 후에도 총 분산은 변하지 않는다.
총 분산의 보존을 이용해 다음을 추론할 수 있다.
- x축 분산과 y축 분산을 단일 백분율 점수로 결합할 수 잇다.
- 데이터를 x축 방향으로 회전하면 x축 분산이 증가하고 y축 분산은 그에 상응하는 수준으로 감소한다. 수직분산을 p% 감소시키면 수평 분산이 p% 증가한다.
x축까지 거리는 다음 과정으로 최소화할 수 있다.
- y축이 차지하는 총 분산 비율을 최소화한다. 그러면 수직 분산을 최소화할 수 있다.
- x축이 차지하는 총 분산 비율을 최대화한다. 그러면 수평 분산을 최대화할 수 있다.
회전 각도에서 전체 분산의 99%가 x축에 분산된다면 회전 데이터는 대부분 1D축 선을 따라 놓일 것이다.
- 데이터 분산이 가로 방향으로 최대화된다.
- 많이 퍼진 데이터는 분리가 쉽다. 분리된 ㄷ데이터들은 서로 구별이 쉽다.
- 수직 Y측을 따른 분산은 최소화되었기 때문에 세로 방향으로는 데이터를 구분하기 어럽다.
- 정보 손실을 최소화하며 모든 Y축 좌표를 제거할 수 있다.
- Y축 좌표를 제거하더라도 전체 분산의 1%미만만 영향을 받으므로 충분히 데이터를 그룹화할 수 있다.
임계값으로 그래프를 세로 분할하여 임계 값을 시각화할 수 있다. 두 임계 값은 그래프를 세 부분으로 나누고, 각 부분은 크기와 상관관계를 가진다.
제한된 데이터 품질을 측정하기 위해 시각화한 것.
- 제한된 데이터는 centered_data의 산점도 중앙을 직접 가로지르는 선을 형성한다.
- 이 선은 데이터의 분산을 최대화하는 선형 방향이 첫 번째 주방향을 나타낸다.
- 대부분의 2D 데이터셋에는 주방향이 두 개 포함된다.
- 두 번째 주방향은 첫 번째 방향과 수직을 이루며, 첫 번째 방향에 포함되지 않은 나머지 분산을 나타낸다.
정리하자면
- 데이터를 뒤집어 2D 고객 측정값 배열을 1차원으로 줄일 수 있다.
- 가로 x축 값만으로도 충분히 데이터를 나눌 수 있다.
- 분산이 최대화되는 주방향을 알면 데이터를 뒤집기가 더 쉽다.
- 첫 번째 주방향이 주어지면 고객 데이터를 차원 축소해 더 쉽게 그룹화할 수 있다.
데이터 회전을 통해 분산을 최대화해 첫 번째 주방향을 추출하는 기법은 더 높은 차원에 적용되지 못한다.
주성분 분석이라는 확장 가능한 알고리즘을 적용하면 모든 주방향을 추출하기 쉽다.
PCA와 사이킷런으로 차원 감소시키기
PCA알고리즘은 데이터셋의 축을 조정해 분산 대부분이 소수의 차원에 분산되도록한다.
데이터를 구분하는 데 모든 차원이 피룡하지 않기 때문이다.
데이터 구분을 단순화할 수 있다면 그룹화 문제도 단순화할 수 있다.
- 2D 데이터셋에 대해 PCA를 실행하면 데이터가 뒤집혀 X축에 수평으로 놓인다. 그러나 데이터의 투영은 특정한 방향으로만 제한되는 것은 아니다.
- 데이터 방향은 다르지만, X축을 따라 분산된 범위는 이전과 일관되게 유지되어야 한다.
첫 번째 주성분이라는 벡터는 첫 번째 주방향이 원점에서 커지는 선분을 의미
첫 번째 주성분은 원점에서 한 단위 길이만큼 늘어나는 크기가 1.0인 단위 벡터
- 대부분의 2D 데이터셋은 주방향을 두 개 포함한다.
- 두 번째 주방향은 첫 번째 방향과 수직을 이루는 특성이 있다.
- 이를 벡터로 표현한 것을 두 번째 주성분이라 한다.
데이터 총 분산의 1% 미만만 포함하는 두 번째 주성분에 관심 가져야하는 이유?
첫 번째 두번째 주성분 모두 데이터의 X축 및 Y축과 특별한 관계를 공유한다. 이 관계를 시각화하면 PCA보다 쉽게 이해할 수 있기 때문이다.
그래프를 보면 주방향 두 개는 본질적으로 X축과 Y축의 회전 버전이다.
축 스압 = 투영이라한다. 두 축을 주방향으로 바꾸는 것을 주방향에 대한 투영이라고 한다.
PCA의 방향이 변경된 출력은 투영에 따라 달라진다. 일반적인 PCA 알고리즘은 다음과 같이 작동한다.
- 각 데이터 포인트에서 평균을 빼서 입력 데이터를 중앙 집중화한다.
- 데이터셋의 주성분을 계산한다. 자세한 계산 내용은 이 절의 뒷부분에서 설명한다.
- 중앙 집중식 데이터와 주요 컴포넌트 사이의 행렬 곱을 구한다. 이렇게 하면 데이터의 표준 축이 주방향으로 바뀐다.
일반적으로 N차원 데이터셋에는 주방향이 N개가 있다. K번째 주방향은 첫 번째 K-1 방향이 포함하지 않는 분산을 최대화한다. 따라서 4D 데이터셋은 주방향을 네 개 갖는다. 첫 번째 주방향은 단방향 분산을 최대화하고, 두 번째 방향은 첫 번째 방향에 포함되지 않은 모든 단방향 분산을 최대화하며, 마지막 두 방향은 나머지 모든 분산을 포함한다.
4D 데이터를 2차원으로 그룹화하기
- 데이터를 2차원으로 축소하려면 데이터를 첫 번째ㅐ와 두 번째 주방향에 투영해야한다.
- 나머지 두 방향은 버릴 수 있기에 분석에는 두 주성분만 필요ㅏ다.
- 사이킷런을 사용하면 PCA 분석을 상위 두 주성분으로 제한할 수 있다.
- PCA(n_components = 2)처럼 PCA객체를 생성해 주면 된다.
- 초기화된 객체는 입력된 데이터를 2차원에 투영하여 축소한다.
특정 게열 꽃(setosa)을 감지하는 간단한 함수를 만든다고 할때,
함수는 꽃잎 측정값 네 개를 담은 flower_sample이라는 네 가지 요소로 구성된 배열을 입력받는다 할 때 다음을 수행한다.
- flower_sample에서 flower_measurements 값의 평균을 빼어 표본을 중심화한다. 해당 평균은 pca_object_2D 객체의 mean_이라는 속성에 저장되어 있으므로 pca_object_2D.mean_처럼 접근할 수 있다.
- 중심화된 표본을 첫 번째 주성분과 내적해 첫 번째 주방향에 투영한다.
- 예상 값이 -2 보다 작은지 확인한다. 그렇다면 해당 flower_sample은 setosa의 유형일 확률이 높다고 판단한다.
간단한 임계 값 분석으로 꽃 샘ㅁ플이 setosa인지 확인할 수 있었는데 이것이 가능했던 것은 바로 PCA 덕분이다.
PCA를 사용했을 때 얻는 이점은 다음과 같다.
- 복잡한 데이터 시각화
- 간소화된 데이터 분류 및 그룹화
- 간소화된 분류
- 메모리 사용량 감소
- 더 빠른 계산
PCA의 제한 사항
PCA는 측정 단위에 지나치게 민감하다.
만약 축 단위를 변경하고, 차원 축소를 진행한다면 이전과 분산이 다른 경우가 발생할 수 있다.
이는 데이터에 오류가 발생한 것이다.
이를 해결하기 위한 해결책은 모든 축이 동일한 측정단위를 공유하도록 하는 것이다. 그러나 측정 단위를 사용할 수 없는 경우가 있다. 축이 서로 다른 측정 유형을 사용하는 경우에는 단위가 호환되지 않는 경우가 있기 때문이다. 이땐 어떻게 해야할까?
축 분산 차이는 값 크기의 차이 때문에 발생한다. 그러므로 정규화를 통해 모든 축이 동일한 바운더리의 값을 가지도록 바꿔주면 될 것이다.
정리하자면
정규화로 기존에 그룹으로 분리된 것은 그대로 유지하면서 단위 차이로 인한 오차를 제거하는 것이다.
그러나 정규화는 의도치 않은 결과를 초래할 수 있다. 정규화된 축 값은 이제 0~1 사이에 있으므로 각 축의 평균도 마찬가지로 0~1 사이에 있다. 모든 값이 평균에서 1단위 미만이다. 이때 부동 소수점의 오류 때문에 데이터를 중심화할 수 없는 상황이 있다. 이때는 실제 평균이 0이 되지 않는다.
그렇다면 정규화된 데이터에 PCA를 안정적으로 실행할 수 없다면 어떻게 해야할까?
회전 없이 밑바닥에서부터 주성분을 계산하는 방법을 배워야한다.
특이 값 분해로 알려진 이 알고리즘을 사용하면 텍스트 데이터를 효율적으로 그룹화할 수 있을 것이다.
회전 없이 주성분 계산하기
centralized_data : 중심화된 측정 데이터셋
first_pc : 측정 데이터셋의 첫 번째 주성분
- first_pc 는 첫 번째 주방향을 가리키는 단위 벡터다. 이 방향은 데이터의 분산을 최대화한다.
- 중요한 점은 모든 분산을 행렬에 저장하면 회전 없이도 주성분을 추출할 수 있다는 것이다.
- 행렬에 전치된 행렬을 곱하고, 데이터 크기로 나누면 공분산 행렬을 만들수있다.
- 공분산 행렬의 대각선에는 각 축에 따른 분산이 담긴다.
- 공분산 행렬과 주성분의 정규화된 곱은 해당 주성분과 동일하다.
- 행렬의 고유 벡터는 행렬과 고유 벡터의 곱이 고유 벡터와 같은 방향을 가리킨다는 특수 속성을 만족한다.
- 행렬과 고유 베터의 곱은 고유 벡터의 방향을 유지한다. 그러나 대부분의 경우 고유 벡터의 크기가 변경된다.
요약
- 첫 번째 주성분은 공분산 행렬의 고유 벡터이다.
- 연관된 고윳값은 첫 번째 주방향에 다른 분산과 같다.
- 데이터셋의 주성분은 데이터셋 공분산 행렬의 정규화된 고유 벡터와 같다.
- 주방향에 다른 분산은 연관된 주성분의 고윳값과 같다.
따라서 첫 번째 주성분을 발견하려면
- 공분산 행렬을 계산한다.
- 행렬의 고윳값이 가장 큰 행렬의 고유 벡터를 구한다. 이 고유 벡터는 분산 범위가 가장 큰 방향에 해당한다.
거듭제곱 반복이라는 간단한 알고리즘을 사용해 고윳값이 가장 큰 고유 벡터를 추출할 수도 있다.
거듭제곱 반복으로 고유 벡터 추출하기
고유벡터 감지를 위한 간단한 알고리즘인 거듭제곱 반복은 다음과 같이 작동한다.
- 임의의 단위 벡터를 생성한다.
- 벡터에 행렬을 곱하고 결과를 정규화한다. 단위 벡터가 회전한다.
- 단위 벡터가 더 이상 회전하지 않는 고착될 때까지 이전 단계를 반복한다. 그러면 정의상 고유 벡터가 된다.
거듭제곱 반복은 고유 벡터에 수렴하도록 보장된다.
결과로 생성되는 고유 벡터는 행렬의 다른 고유벡터에 비해 가능한 가장 큰 고윳값을 갖는다.
❗일부 행렬에는 음의 고윳값을 갖는 고유 벡터가 있다. 이 경우 거듭제곱 반복은 절대 고윳값이 가장 큰 고유 벡터를 반환한다.
두 번째 고유 벡터를 추출하려면 cov_matrix에서 첫 번째 고유 벡터의 흔적을 모두 제거해야하 한다. 이 과정을 행렬 수축이라 한다.
기본적으로 모든 행의 평균이 0인 행렬에서 상위 주성분 K개를 추출하는 알고리즘을 만들었다.
centered_matrix 같은 행렬이 주어졌을 때 알고리즘은 다음과 같이 작동한다.
- centered_matrix를 centered_matrix.T로 centered_matrix의 공분산 행렬을 계산
- 공분산 행렬에 power_iteration을 실행, 이 함수는 공분산 행렬의 고유 벡터를 반환하며, 이는 가능한 최대 고윳값에 해당한다. 이 고유벡터는 첫 번째 주성분과 같다.
- 행렬에 고윳값*np.outer(고유벡터,고유벡터)를 빼 행렬을 수축한다. 수축된 행렬에 power_iteration을 실행하면 그 다음 주성분을 추출할 수 있다.
- 이전 단계를 K - 2번 더 반복해 상위 주성분을 K개 추출한다.
데이터셋에서 상위 주성분을 K개 추출하는 함수를 정의했다. 이것으로 데이터셋을 상위 주방향 K개에 투영할 수 있으며 해당 방향은 K축을 따라 데이터 분산을 극대화한다. 나머지 데이터 축은 무시할 수 있으므로 좌표 열 크기를 K로 축소할 수 있고, 결과적으로 모든 데이터셋을 K차원으로 줄일 수 있다.
이젠 사이킷런 없이도 PCA를 실행할 수 있다. PCA를 사용하면 N차원 데이터셋을 K차원으로 줄일 수 있다. 알고리즘은 다음 단계를 거쳐 실행된다.
- 데이터셋의 각 축을 따라 평균을 계산한다.
- 모든 축에서 평균을 빼서 데이터셋의 원점 중앙에 맞춘다.
- find_top_pricipal_components 함수로 중심 데이터셋의 상위 주성분을 K개 추출한다.
- 주성분과 중심 데이터셋 사이의 행렬 곱을 구한다.
정규화된 데이터에서는 중심화를 안정적으로 수행할 수 없다 이때 대안은 centralize_data = False 파리미터 값을 입력해 중심화를 우회하는 것이다.
중심화 없이 값을 줄이면?
위와 같이 중심화 없이 줄일 수 있다. 하지만 이건 특이 값 분해라고 하는 다른 이름으로 불린다.
SVD 및 사이킷런으로 효율적인 차원 축소하기
사이킷런의 최적화된 SVD로 수십 테라바이트에 달하는 데이터를 수백 또는 수십 개 차원으로 축소할 수 있다. 축소된 데이터는 예측 알고리즘을 이용해 좀 더 효율적으로 저장, 전송, 처리될 수 있다. 많은 실제 데이터 작업에서 분석에 앞서 데이터 축소하는 데 SVD를 사용한다. SVD를 사용하면 대부분의 분산은 유지하면서 텍스트 행렬의 열 수를 줄일 수 있으므로, 대규모 텍스트 유사도를 적시에 계산할 수 있다. 그다음 이렇게 계산된 텍스트 유사도로 문서를 그룹화할 수 있다.
15장 대용량 텍스트에 대한 자연어 처리 분석
이 장에서는 대규 텍스트 데이터셋에 대해 자연어 처리를 적용해본다.
글의 내용을 주제별로 어떻게 묶을 수 있을까? 다음은 한 가지 접근법을 보여 준다.
- 13장에서 설명한 기법으로 모든 토론 텍스트를 단어 수의 행렬로 변환한다.
- 특이 값 분해(SVD)로 단어 수 행렬을 차원 축소한다. 이렇게 하면 행렬 곱셈으로 모든 텍스트의 유사성을 효율적으로 계산할 수 있다.
- 텍스트 유사성 행렬을 활용하여 토론을 주제별로 묶는다.
- 주제 그룹을 탐색해 마케팅 캠페인에 유용한 주제를 파악한다.
사이킷런으로 웹 토론 포럼 데이터셋 불러오기
- 사이킷런은 잘 알려진 웹 토론 포럼인 Usenet의 데이터를 제공한다.
- 이 포럼을 뉴스 그룹이라 한다.
- 게시글의 다양성과 다양한 길이 모두 자연어 처리 기술을 확장할 기회를 제공한다.
- 데이터셋에는 게시글이 1만 1,000개 이상 포함되어 있다. 우리 목표는 이 게시글을 주제별로 그룹화하는 것이지만, 이 정도 규모의 텍스트를 그룹화하려면 계산이 효율적으로 수행될 수 있어야한다.
- 텍스트 데이터를 행렬로 표현해 뉴스 그룹 게시글의 유사성을 효율적으로 계산해야한다.
- 이를 위해서는 각 뉴스 그룹 게시글을 용어 빈도 벡터로 변환해야 한다.
사이킷런으로 문서 벡터화하기
사이킷런은 입력 텍스트를 TF 벡터로 변환하는 CountVectorizer라는 내장 클래스를 제공한다.
CountVectorizer를 초기화하면 텍스트를 벡터화할 수 있는 Vectorizer 객첵가 생성된다.
사용법은 단순히 Vectorizer를 호출하기만 하면 된다.
이 호출은 벡터화된 뉴스 그룹 게시글에 해당하는 TF 행렬을 반환한다.
참고로 TF행렬은 모든 텍스트(행)에 포함된 단어 수(열)을 저장한다.
해당 행렬은 csr_matrix라는 사이파이의 객체이다.
CSR
- 압축된 희소 행의 약어
- 대부분 비어 있는(0) 이러한 행렬을 희소 행렬이라고 한다.
- 0이 아닌 요소만 저장하여 공간을 효율적으로 만들 수 있으며, 이는 곧 보다 효율적인 메모리 사용과 빠른 계산으로 이어진다.
- 대규모 텍스트 기반 행렬은 일반적으로 단일 문서에 전체 어휘의 극히 일부만 포함되기 때문에 매우 희소하다고 볼 수 있다.
- 따라서 사이킷런은 벡터화된 텍스트를 CSR 형식으로 자동 변환한다.
- 이 변환은 사이파이의 csr_matrix 클래스로 수행된다.
주의
넘파이 배열과 CSR 행렬은 일부 속성을 공유하지만 모든 속성을 공유하지는 않기 때문에 초보자에게 혼란스러울 수 있다.
또 CSR 행렬은 넘파이가 제공하는 일부 함수에 호환되지만 모든 함수와 호환되지는 않는다.
따라서 tf_matrix 를 2D 넘파이 배열로 변환하여 혼란을 최소화.
각 행렬 요소는 게시글에 포함된 단어 수를 표현한다. 행은 게시글을, 열은 개별 단어를 나타내는 식이다.
따라서 총 열 개수는 데이터셋의 어휘 크기와 같다.
자연어 처리 실무자들은 잡음이 많은 단어를 중지 단어라고 한다. 중요한 단어가 벡터화된 결과에 나타나지 않도록 차단하기 때문이다. 중지단어는 일반적으로 벡터화되기 전 삭제된다.
관련성 기준으로 단어 순위를 매길 땐 게시글의 빈도와 횟수를 모두 활용해야 한다. 두 단어의 등장 횟수가 같다면 그때는 게시글 빈도로 순위를 매겨야 한다.
게시글 빈도 및 개수로 단어의 순위 매기기
df.Word의 단어 34개는 각각 뉴스 그룹 게시글에서 특정 비율로 나타난다.
자연어 처리에선 이 비율을 단어의 문서 빈도라고 한다.
단어 수와 문서 빈도를 점수 하나로 결합해 과정을 단순화할 수 있을 것이다. 어떻게 하면 될까?
한 가지 접근법은 각 단어 수를 관련 문서 빈도로 나누는 것이다. 다음 중 하나에 해당하면 결과 값이 증가한다.
- 단어 수가 증가한다.
- 문서 빈도가 줄어든다.
단어 수와 문서 빈도를 단일 점수로 합쳐 보겠습니다. 먼저 1 / document_frequencies를 계산한다. 이렇게 하면 역문서 빈도 (IDF)배열이 생성된다.
역문서 빈도는 쉽게 말하면 자주 등장하지 않는 단어일수록 더 중요한 단어를 의미한다.
IDF 값을 작게 만들어야할 때 데이터 값을 축소하는 한 방법은 로그 함수를 적용하는 것이다.
단어 빈도-역문서 빈도(TFIDF)를 사용하면 자주나오지만 관련성 없는 단어를 지우고 정말 중요한 단어들을 뽑아낼 수 있다.
- TFIDF는 TF(단어 수)와 IDF의 로그 곱을 취하여 계산할 수 있다.
- TFIDF는 문서에서 단어 순위를 매기는 간단하지만 강력한 지표이다.
- 이 지표는 해당 문서가 더 큰 문서 그룹의 일부일 때만 관련이 있다. 그렇지 않으면 계산된 TFIDF값은 모두 0이 된다.
- 유사한 테스트의 소규모 컬렉션에 적용될 때 그 효과를 잃게 된다.
- 그럼에도 대부분의 실제 텍스트 데이터셋의 경우 TFIDF는 좋은 순위 결과를 산출한다.
- 문서에서 단어를 벡터화하는 데 활용할 수도 있다.
TF 벡터를 더 복잡한 TFIDF벡터로 변환하면 이점이 있을까?
그렇다. 더 큰 텍스트 데이터셋에서 TFIDF벡터는 텍스트의 유사성과 차이에 대한 더 큰 신호를 제공한다.
사이킷런으로 TFIDF 벡터 계산하기
직접 계산한 Combined 열의 상위 열 개 값은 모두 1보다 크지만 사이킷런으로 계산한 TFIDF 열의 값은 모두 1보다 작다.
이는 사이킷런이 TFIDF 벡터를 자동으로 정규화하기 때문이다. df. TFIDF 열의 모든 값을 더했을 대 1이되도록 수정한 것이다.
사이킷런이 벡터를 자동으로 정규화하는 이유는 무엇일까?
모든 벡터의 크기를 더한 값이 1이면 텍스트 벡터 유사도를 더 쉽게 계산할 수 있다. 따라서 정규화된 TFIDF 행렬은 유사도 분석을 위한 준비까지 자동으로 해 준 셈이다.
대규모 문서 데이터셋의 유사성 계산하기
뉴스 그룹의 게시글 중 newgroups.post[0]와 가장 유사한 것은 무엇일까?
코사인 유사도를 계산하면 답을 구할 수 있다. 행렬의 모든 행 크기가 1이기 때문에 행렬과 벡터 간 단순 곱셈으로 충분하다.
전체 코사인 유사도 행렬은 어떻게 계산할 수 있을까?
가장 간단한 접근은 tfidff_np_matrix에 스스로를 전치한 행렬을 곱하는 것이다.
하지만 행렬 곱셈은 효율적이지 않기에 행렬 곱셈 전에 먼저 행렬 크기를 줄어야한다.
대부분의 자연어 처리 실무자들은 n_components = 100으로 설정되었을 때, 유용한 열 정보를 유지하면서 TFIDF 행렬을 효율적인 크기로 줄인다는 데 동의한다.
주제별로 텍스트 그룹화하기
K-평균은 유클리드 거리로 그룹화가 가능한 반면, DBSCAN은 모든 거리 지표를 기반으로 그룹화가 가능하다.
코사인 거리를 예로 들 수 있다. 코사인 거리는 1에서 코사인 유사도를 뺀 값이다.
코사인 거리는 일반적으로 DBSCAN과 함께 사용된다. 그렇기에 사이킷러너이 제공하는 DBSCAN 구현체를 사용하면, 객체르 ㄹ초기화할 때 코사인 거리를 지표로서 직접 지정할 수 있다.
연구에 따르면 K-평균은 텍스트 데이터를 합리적으로 세분화할 수 있다. 하지만 데이터 과학에서 올바른 알고리즘을 선태개하는 것은 문제 도메인에 따라 다르다. 단일 알고리즘으로 모든 유형의 문제를 해결하는 것은 불가능에 가깝다.
K-평균이 실행되는 시간은 어떻게 단축시킬 수 있을까?
한 방법은 방대한 데이터셋을 임의로 샘플링하는 것이다.
K-평균의 중심이 계산되는 동안 임의로 게시글을 1000개 선택, 또 다른 임의의 게시글을 1000개 선택해 그룹의 중심을 갱신하는 방법이다. 이 방식으로 반복적으로 중심을 추정할 수 있다.
이 방식을 미니배치 K-평균이라 한다.
미니배치 K-평균은 일반 K-평균보다 약 10배 빠르다.
이 실행 시간 단축은 약간의 희생을 수반한다. 미니배치는 약간 낮은 품질의 그룹화 결과를 생성하기 때문이다.
그러나 그룹화 품질이 아니라 K 파라미터 값을 추정하기 위해 1~60 범위의 엘보 플롯을 만드는 데 관심이 있다.
추정 도구로 미니배치 K-평균의 역할은 충분하다.
K = 20 이후로 어딘가에서 곡선이 평평해지기 시작하지만, 팔꿈치가 갑자기 구부러지는 특정 위치는 없다. 즉, 완벽한 K 값은 없는 것으로 보인다. 왜그럴까?
우선 현실의 텍스트는 매우 지저분하며 차이가 매우 미묘할 수 있어서 정확한 범주의 경계를 명확히 세울 수 있지 않기 때문이다.
게시글들의 관련성을 어떻게 평가할 수 있을까?
모든 게시글에서 상위로 순위가 매겨진 단어를 표시해 콘텐츠를 집계하는 방법을 활용할 수 있다.
각 인덱스에서 각 단어의 TFIDF를 합산하여 순위를 매긴다. 그다음 집계된 TFIDF를 기준으로 단어를 정렬한다.
상위 열 개 단어를 출력하면 콘텐츠가 어떤 콘텐츠와 관련이 있는지 판단하는 데 도움이 된다.
상위 키워드를 조사함으로써 클러스터로 묶인 게시글을 일일이 읽지 않고도 그룹의 유효성을 검사할 수 있었다..
텍스트 클러스터 시각화하기
우리 목표는 여러 텍스트 클러스터에 걸쳐 순위가 매겨진 키워드를 시각화하는 것이다.
단일 클러스터에서 중요한 키워드를 어떻게 시각화할 것인가라는 간단한 문제를 먼저 해결해야한다.
한 가지 방법은 키워드를 중요도 순서대로 출력하는 것이다. 안타깝게도 이 정렬 방식은 상대적 중요도에 대한 감각이 부족하다.
상대적 중요도를 시각화에 어떻게 통합할 수 있을까?
글꼴 크기로 중요성을 나타낼 수 있다. 글꼴의 크기가 너무 작을 땐, TFIDF 중요도 점수의 합계를 2배로 늘리면 글꼴 크기를 더 크게 만들 수 있다.
또한 맷플롯립의 plt.text 함수를 이용하면 단어 크기가 중요도에 비례하는 2D 격자에서 단어를 시각화할 수 있다.
이러한 유형의 시각화를 워드 클라우드라고 한다.
'소프트웨어 > 데이터 분석' 카테고리의 다른 글
실전 데이터분석 1주차 (0) | 2025.04.02 |
---|