20221122화-오프라인팀미팅, 멘토링, 오아, dkt7
멘토 숙제
차원축소 감잡기
- 1 dimensional manifold in R^2: 원, 2 dimensional manifolds in R^3: 구, 토러스, 원기둥
- 각 도형의 매개변수식을 위키피디아에서 검색.
- 넘파이로 각 도형의 포인트들을 랜덤 샘플링해서 저장.
- 높이를 기준으로 각 포인트의 색을 지정.
- PCA, MDS, ISOMAP, LDA, tSNE로 매개변수 차원으로 축소한 뒤 지정된 색에 따라서 시각화.
- 팀원들과 각 차원 축소법이 어떤 특징을 가지고 있는지 토의.
숙제 우리가 잘 아는 도형이 있다. 원, 구, 토러스, 원기둥. 4가지 도형을 paramerized form으로 써진 것이 있음. 첫째 빼고는 다 3차원. 매개변수 방정식을 찾아보라. 막상보면 3차원 애들은 파라미터가 2개로 다 같다.
그러한 3차원 정보가 생길 것인데 , 이것에 대해서 PCA, MDS, SNE, ISOMAP
높이로 색깔을 줄 것. 높으면 빨간색을 가지고 점차 파랑색으로 간다던지. 그렇게 데이터 분포를 두는데, 이걸 차원 축소를 했을 때 어떻게 분포가 되는지, 그래서 그것의 특징이 무엇인지를 추측해서 가져오라.
원기둥은 높이를 100정도로 잡아라, 즉 길쭉하게 하라는 것. 원기둥의 그 기둥에 점이 분포하게 된다.
구도 안 쪽에 점이 들어가지 않는다. 구글링하면 바로 나온다.
키워드. circle, sphere, torus, cylinder! sklearn에 구현이 되어있으니 찾아보라.
이를 통해 도형들의 특징을 알 수 있고 각 방법이 어떤 의미를 가지는지 알 수 있다.
개념적으로 수식이 어떤지를 알고자하는 것이 아니라, 어떤 의미를 가지는지를 따져볼 것. 차원축소의 맹점.
잘은 모르겠지만, 일단 원부터 해보자고. Kernel PCA — scikit-learn 1.1.3 documentation
Kernel PCA
This example shows the difference between the Principal Components Analysis ( PCA) and its kernalized version ( KernelPCA). On the one hand, we show that KernelPCA is able to find a projection of t...
scikit-learn.org
편하게 쓸 수 있는 예제가 있는 듯하다.
대충 이런 식으로 결과를 내고 있다. 그러나 이건 내가 원하는 원이 아니다. 나는 그냥 원을 바란다!
직접 만들어보지 뭐.
예상치 못한 결과. 생각해보니 그냥 원의 방정식은 원점을 중심으로 두니 당연한 결과이기도 하다.
음.. 원 구현을 어떻게 해야 할지 모르겠다. 그러고보니 데이터 시각화 예제에서 원을 그리는 모습을 보여줬던 것 같다.
이거였구만!
흙흙.. 어떻게 써야할지 도무지 감이 잡히질 않는다. 나에게는 짧은 시간으로 해결할 수 없는 과제인 것 같다.. 급한 대로 각 차원 축소 기법의 특징과 개념만 한번 알아보자.
pca. 주성분 분석. 원데이터의 분포를 최대한 보존하면서 저차원 공간으로 변화. 기존의 변수를 조합해 연관성이 없는 새로운 변수, 주성분들을 만든다. 11차원의 데이터를 같은 갯수의 주성분들로 만드는데, 이때 3개의 주성분이 실 데이터의 90퍼를 가진다면 그것만 가지고 가면 3차원으로 줄일 수 있다는 마인드.
주성분을 구하려면 새로운 축을 찾는다. 이것이 주축이라 불리고, 원 데이터들을 정사영할 때 가장 잘 반영되도록 정한다는 듯.
그리고 이와 수직이 되도록, 독립이 되도록 두번째 축을 찾는다. 계속 이런 식으로 찾아나간다는 듯.
멘토 숙제 - 협업
혼자 풀기는 어렵다는 것을 받아들이고, 팀원들과 만나 역할 분담을 하고 의견 공유를 하면서 진행했다. 그중에서 나는 토러스를 한번 구현해보기로 했다.
토러스 방정식. / 토러스(torus) (tistory.com) 여기에서 코드를 적극적으로 참조해서 만드는 중.
아주 그럴싸한 모양이 나왔다!
성훈이 형이 옆에서 같이 했는데, 나 혼자였으면 우물쭈물했을 텐데 일사천리로 일이 진행됐다!
np.random.seed(42)
fig = plt.figure(figsize=(plt.figaspect(0.7)))
ax = fig.add_subplot(111, projection='3d')
n = 64
U = (np.random.random(n ** 2) * 2*np.pi).reshape(n,n)
V = (np.random.random(n ** 2) * 2*np.pi).reshape(n,n)
a = 3
b = 0.5
X = (a + b * np.cos(V)) * np.cos(U)
Y = (a + b * np.cos(V)) * np.sin(U)
Z = b * np.sin(V)
W = Z.reshape(-1)
surf = ax.scatter(X,Y,Z, c=W, cmap='Greens',
linewidth=0.01, antialiased=False, alpha = 0.5)
ax.set_zlim3d(-2.01, 2.01)
fig.colorbar(surf, shrink=0.5, aspect=10)
plt.show()
lst = []
for x,y,z,w in zip(X.reshape(-1),Y.reshape(-1),Z.reshape(-1), W.reshape(-1)):
lst.append((x,y,z,w))
lst = np.array(lst)
X = lst[:, :-1]
y = lst[:, -1]
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X)
# pca.explained_variance_ratio_
pca_X = pca.transform(X)
print(pca_X)
plt.scatter(pca_X[:, 0], np.zeros(len(X)), c=y, cmap='Greens', alpha=0.8);
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2)
tsne_X = tsne.fit_transform(X)
tsne_X
plt.scatter(tsne_X[:, 0], tsne_X[:, 1], c=y, cmap='Greens')
from sklearn.manifold import MDS
mds = MDS(n_components=2, verbose=1, max_iter=10)
mds_X = mds.fit_transform(X)
mds_X
plt.scatter(mds_X[:, 0], mds_X[:, 1], c=y, cmap='Greens')
from sklearn.manifold import Isomap
iso = Isomap(n_components=2)
iso_X = iso.fit_transform(X)
iso_X
plt.scatter(iso_X[:, 0], iso_X[:, 1], c=y, cmap='Greens')
내가 멘토링 받기전에 팀원들과 공부하며서 준비한 것들.
멘토링
일단 팀원들이 한 것들에 대하여.
원은 완전히 다하지는 못 했다. 다만 원에서 얻게 된 인사이트들을 바탕으로 다른 도형들을 거침없이 구현해냈다! 간단하게 보자면 2차원의 원을 정말 옆으로 뉘어서 본 듯한 모습이다. 멘토님의 설명으로는 중간에 선을 긋고 그 선에 점들을 갖다붙인 모습이라고.
승렬이가 구현한 구. normal을 사용해서 무작위 수를 골랐는데, 어차피 random sampling이라 크게 상관은 없을 것으로...
상준이와 수헌이 형이 구현한 원기둥. pca를 진행하면 원기둥을 옆에서 누른 듯한 모습이 나오고,
tSNE를 쓰면 왼쪽 모습이 나온다! 마치 군집화가 일어난 듯한 모양이다. 오른쪽은 isomap을 쓴 것인데, 뭔가 잘 표현되지는 않은 모습. 나중에 보니까 조금 수정하면 이것도 잘 표현되게 할 수는 있더라.
마지막으로 토러스. 기본 코드는 내가 웹 글을 참고해서 따라쳤지만, 실질적으로 수정 작업은 성훈이 형이 다 했다. 이걸 본 것만으로도 어느 정도 공부가 된 것 같다. 그러나 복습을 하지 않으면 금방 잊을 수 있기에 다시 참고.
일단 3d로 그릴 도화지 하나 마련. U, V로 그릴 범위를 마련한다. 이때 random하게 하여 scatter의 참맛을 살린다! 어째서 n의 제곱을 하는가? 원래 코드에서는 meshgrid를 통해 행렬 단위로 한 차원을 올린다. 이 작업은 정직하게 격자를 늘리는 작업을 해준다.
그래서 단순하게 meshgrid를 하면 이런 모양이 나온다(핵심은 도넛의 모양이 균일하다는 것). 이를 바꿔주기 위해서 아예 n제곱으로 뽑은 다음에 이후에 reshape으로 (n,n)으로 모양을 잡아주는 것.
그 다음, 상수 값을 조절하면서 토러스 방정식을 세우고 scatter를 찍어주면 저 모습이 나오게 된다. W를 색을 나타내는 변수로 따로 지정을 해줬으며, cmap으로 전체 색 스타일을 지정한다. 다른 옵션들은 크게 중요하지는 않다. 다만 alpha는 투명도를 나타내는 지표.
이것을 lst에 담는 것은 적합한 x,y,z 쌍을 찾아서 묶어주는 것. 이를 해야 차원 축소를 진행할 수 있기 때문이다. pca는 위에서 붙여놓았기 때문에 생략.
이것이 토러스의 tsne. 잘 군집화가 되지도 않았고, 심지어 제대로 차원 축소가 되었다고 보기도 힘들다.
비슷한 방식으로 mds, isomap까지 한 모습이다. 대체로 위에서 도넛을 누른 듯한 모습으로 차원 축소가 일어난 것이 확인된다.
아래부터는 강의 내용 정리.
mds는 원래 시간이 걸린다. isomap과 pca는 모양이 비슷하게 나온다. 원기둥의 경우, isomap 파라미터를 바꿔 제대로 모양을 찍어낼 수도 있다. 이때 n_neighbors와 radius 둘 중에 한 인자만 줄 수 있으니 참고.
pca는 svd 응용, 내지는 한 종류라고 생각할 수 있다. svd란? 선형변환을 더 작은 파츠로 찢어서 차례대로 곱하는 연산을 하는 것. 그래서 사실 projection정사영과 다를 것이 없다.
여기에서 대각행렬 중 중요한 성분을 빼내는 것. 그것이 곧 pca라고 볼 수 있으며, 이는 우리가 주성분을 골라, 우리가 보는 시점을 정하는 것과 같다.
pca에 대한 좋은 설명. 우리의 우주는 3d로 이뤄져 있는데, 우리는 밤하늘에서 차원 축소된 우주를 본다. 태양계를 생각해보라. 궤도를 잘 보기 위해 위에서 보면 2차원으로 축소, 그냥 행성 간 거리 확인을 위해 1차원으로까지 축소시킬 수도 있다.
행렬은 선형 변환을 뜻하기도 한다. 선형 변환이란? 벡터 공간과 벡터 공간 사이에서 정의되는 함수이며 선형성을 성질로 가진다. 이는 순서를 어찌 해도 같다 정도의 의미. 그러나 우리는 행렬이 어떻게 변환을 시켜주는 것인지, 정확하게는 알 수가 없는데 이를 표현해주는 것이 차원 분해라고 볼 수 있다.
isomap은 불안정하다. 몇 지점에서 그래프를 잇고 이은 것으로 토대로 표면을 그린다. 그래서 일종의 군집화하는 느낌이 난다. 원기둥원 원래 도넛 같은 모양으로 바뀐 뒤에 표시가 됐을 것. 참고로 군집화를 시각화해서 보이는 것은 대체로 의미가 없을 때가 많다. isomap의 군집화는 그다지 효과적이지 않을 수 있음. 차원을 줄여서 표현을 하기때문에. 군집화가 제대로된 것인지 표현하는 것이 아닐 수 있음. 제대로 군집화가 됐다고 보기 어려울 수도 있다는 것.
mds는 모든 포인트에서 다른 모든 포인트로 거리를 잰다. 그다음에 그 거리를 유지하면서 차원을 낮춘다. 길이가 변하지 않는 연산. 그걸 iso metric이라 하는데, 물론 완벽하게 그 거리를 유지하는 것은 불가능하다. mds 알고리즘은 많은데, 이중에서 가장 나이브한 건 결국 pca랑 같기에 모양이 똑같이 나오는 것이다. stress function을 만들어서 이걸 최소화하는 방향으로 학습을 하는데 max_iter가 있는 이유가 여기에 있다. 그래서 끊는 지점도 존재한다.
tsne는 거리가 좀 먼 것들을 가까이 모아주는 경향이 있다. 시각화됐을 때 항상 조심하라. 눈에 보이는 것으로 그런 것을 제대로 확인할 수 없는 경우가 많다. 시각화의 맹점이라고 볼 수 있다. 그럴듯하게 시각화로 생각을 속이는 짓을 하지 말자! 속지도 말자(하기엔 나는 보자마자 속을 것 같다 ㅋㅋ 눈으로 보이는 군집화 어떻게 참냐고)!
pca 같은 차원 축소를 왜 하는가? 축소를 통해 볼 수 있는 것들도 있으니까. 밀집화를 통해 새로운 것이 보이는 경우가 있고, 희소한 것에 대해서 다양한 시도를 할 수 있게 도와준다. flat하지 않을때, 클러스터링을 하듯이 조금 분류를 하는 느낌인 것이다. 또, 이상치 소거를 하는 방향으로도 생각해볼 수도 있다. 즉e da에 사용가능하다는 것!
다음주 숙제!
embedding이 무엇인지. 각자 찾아서 자기만의대답으로 만들어라.
attention에서 query, key, value. 차원은 서로 페어가 된다.
q와k는 같은 차원으로 임베딩된다. v는 다른 차원.
근데 k와 v의 데이터는 같고, q는 틀리다.
이게 무얼 뜻하는지 파악하는 게 숙제. 그리고 이용어들이 어떤 의미를 지니는지도 맞물려 생각해보라.
왜 포지셔널 인코딩 초창기 모델은 삼각함수를 사용한다. 이게 어떻게 돼 있고, 왜 좋은지 알아보자.
페이지 랭크. 알고리즘의 한 종류. 구글의 초기 검색 엔진.
이전에는 키워드 검색을 하면 그 키워드 관련 문서들이 뜨는데, 아무런 규칙없이 나열했다. 좋은 서치는 아니었다. 진짜 필요한 순으로 나열해줘야 좋은 거지. 그래서 문서마다 중요도를 고려하는게 또 한 포인트였다. 이를 하이퍼링크로 정의하고는 했음. 인용된 횟수. 링크 걸면 페이지 타고가잖냐. 이를 이동이라고 생각하고, 이게 무한히 반복되면, 사람들이 어디에 머무르게 될까? 이것에 대해 관심을 가지기 시작한 것.
이러한 이동 행렬을 생각해볼 수 있다. 그래프로 나타낼 수 있으니까. 연결된 간선을 다 같은 값으로 생각하기. 이걸 통해 어디에 가장 많이 유입되는지, 스코어가 나온다. 결국 많이 연결되면 높은 점수를 얻으니. 이걸 통해 추천을 해준다.
근데 이런 식으로 하면 정보 소실의 문제가 생길 수 있따. 구글은 여기에서 google matrix를 만든다.
정보가 소실되지 않도록, 간혹 점프하는 능력을 주는 것.
아래는 차마 정리가 안 돼서.. 그냥 남겨둔 것. 뭔가 느낌은 살짝 오지만 완벽하게 캐치는 안 되는 느낌이다.
모든 컬럼을 평균내서 각각 빼준다. $\frac{1}{n-1}AA^E$ 대칭행렬. 이런 것은 좋은 성질이 있고, svd는 이를 만들고자한다. 자신의 전치가 자기 자신과 같다. 이는 분해가 가능하다. 이로부터 singular matrix와vector를구한다. 그렇게 만들어진 svd의 앞 행렬.이것에서 pca는 중요한앞놈들만 남긴다. 상위를 몇개를 남길 것인가가 바로 pca의 핵심.데이터를 어떤 시점으로 볼 것인가 -- 정사영(projection)pca는 svd의 한 종류라고 볼 수 있다. 그리고 주성분을 몇개에 두냐에 따라 우리가 보는 시점을 정하는 것과 같다.
eigenvalue, eigenvector. 행렬 == 선형변환. 선형변환은 벡터공간과 벡터 공간 사이에서 정의되는 함수. 성질: 선형성. linearity. 순서를 어찌해도 같다, 정도가 선형성의의미. 그래서 행렬이 어떻게 해주냐. 어떤 공간의x를 행렬로 변환. 근데 우리는 이 행렬이 어떻게 움직이는지 모른다.이를 편하게 보게 해주는 것. 이것이 일종의 분해, decomposition인 것이다.eigendecomposition. $a = udu^t$u는 orthogonal. 전치 행렬이 역행렬과 같다. 이를 활용해서 이 행렬을 앞뒤에 붙인 행렬의 제곱은 매우 단순하게 표현된다. 연산의 편이성. 비행기의 방향전환에서. eigenvalue를활용하여 한쪾 출력 높이고 다른 쪾 낮추는 정도를 게산.지금 우리 내용에서는, 한 벡터를 없앤다. 이게 projection.. 이것은 항상할수는 없다. 제한이 있다. 일단 A가 symmetric이면 항상 가능. 정사각행렬이어야 한다. 역행렬이 나와야 하기 때문이다. 그러나 svd화시켜서 할 수 있음.
오피스아워
금융권의 추천시스템. 많은 종류의 데이터를 모아서 추천하면서 겪은 것들. 테이블로 구성하는 것이 첫번째 작업. 그리고 어떤 테이블을 쓰는지 구성. 자료로 구성하는 것도 일이다. 데이터를 저장하고 나서도 쿼리 최적화에 따라 데이터를 뽑는 속도도 달라짐.
금융 추천모델 개발. 각 사람마다 상품 가입 주기가 매우길다. 거의 6년 정도. 또한 금융 상품은 트렌드에 맞게 지속적으로 변화. 그래서 개인화된 추천의 효율이 떨어졌다. 상품 별 가입 선호도를 뽑고, 전화나 문자를 통한 리뷰를 받아야 하기도 했다.
그래서 금융권에서 필요한 역량은? 금융 도메인에 대한 이해. 그리고 데이터를 관리하는 db와 쿼리에 대한 이해. 해당 도메인에 대한 최적화된 마케팅 이 3가지로 정리할 수 있다.
이 분야에서 주의할 것
과연 모델의 성능만이 중요한가? 88퍼와 83퍼의 성능을 가진 모델이란 사실만 있다면, 당연히 88퍼를 선택할 것이다. 근데 추론 시간이 4시간이고 10분이고, 모델 운용비가 10만원과 천원의 차이라면?
정말 성능만이 중요할까? 그것 말고도 용량, 가용자원, 추론시간도 전부 중요한 요소이다.
성능만 추구하기보다는, 다양한 시도를 하면서 그 이유를 찾고 경험을 쌓는 것이 중요하며, 면접에서도 그러한 것에 대한 자기소개가 도움이 된다. 당장 현재의 평가지표에서의 1등을 하는 것보다, 베이스라인 구축이나 새로운 모델, 다양한 라이브러리 적용등의 경험을 하면서 스토리라인을 만들어나가라. 주어진 베이스라인에서 파라미터만 간단하게 수정하는 것에서 벗어나라. 과감히 버려라. 모든 데이터를 활용할 수 있는 파이프라인을 구축하는 게 좋다. 편한 것에 불편함을 느껴라! 일부만 활용하지 말고 전체를 구현하자!
또 왜 이 대회가 개최됐을까 생각해보자. 지금 dkt는 어째서 하고 있는가?
ai를 왜 적용해야 하는지, 실무에서 어떤 점에서 필요한지에 대한 설명을 개진할 수 있어야 한다.
가령 투자비용 대비 마케팅 성공률이 올라가고, 타겟 대상이 명확해진다는 등을 통해 계획이나 예상 비용과 효용을 계산하는 것. 이를 통해 정확한 투자비용을 설계하고, 그로부터 나오는 효율을 제시하는 것이 필요하다.
ai가 필요한 이유에 대해 현업에서 비즈니스적 가치를 제시하는 것. 무엇이 ai인지, 왜 ai인지, 어떻게 ai인지 등을 고민해보는 게 좋다.
회고 및 다짐
오늘 오프라인으로 팀원들과 만나서 이야기하고, 과제를 진행하는 것은 굉장히 도움이 됐다. 혼자서는 절대 하지 못할 것들을 해나갈 수 있었고, 다양한 의견 교환을 할 수 있었다. 멘토링 이후에는 성훈이 형의 노력으로 완성된 베이스라인 코드를 확인하고, 이후에는 어떻게 피쳐 엔지니어링을 할 수 있을지와, 검증 방법에 대한 논의를 더 이어나갔다.
추가적으로 내가 관심 가지고 있는 사안에 대해서도 이야기를 했는데, 말을 하는 과정에서 머릿속에서 조금씩 더 정리되는 무언가가 있었다. 과연 문항의 갯수는 무얼 뜻하는 것일까. 모른다. 모르지만 모델은 알 수도 있다! 일단 노션에 정리해놨으니 팀원들이 읽고 더 의견을 제시해줄지도 모르겠다.
그나저나 내가 EDA에 당장 몰두하고 있기는 한데, 팀적으로 효율이 나오고 있는지에 대해서 확신이 없다. wandb는 사실 조금만 사용법을 익히면 꽤 쉽게 적용할 수도 있을 것 같은데, 이것을 내가 파보는 것이 좋을지도 모르겠다고 생각이 든다. 아무래도 내가 생각해둔 사안들을 어느 정도만 하고 나면 나는 wandb를 파볼까 한다. 전번 1등 팀이 wandb를 통해서 어떤 피쳐가 유의미한지를 밝혀냈다고 했던 것 같은데, wandb를 잘 활용하면 피쳐 엔지니어링에 있어 큰 도움이 되지 않을까 한다.
근데 내가 생각해둔 것들이 꽤 되는데, 이것을 내가 직접 해낼 수 있을지 의문이다... 실력이 따라가질 못 한다!