<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yoonie.log</title>
        <link>https://velog.io/</link>
        <description>호로록</description>
        <lastBuildDate>Sun, 24 Nov 2024 17:03:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yoonie.log</title>
            <url>https://velog.velcdn.com/images/yoonie_03/profile/8e91a47e-82d0-4324-8a6b-ad34d95ca5ea/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yoonie.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/yoonie_03" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]9장 9.1 군집]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning9%EC%9E%A5-9.1-%EA%B5%B0%EC%A7%91</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning9%EC%9E%A5-9.1-%EA%B5%B0%EC%A7%91</guid>
            <pubDate>Sun, 24 Nov 2024 17:03:47 GMT</pubDate>
            <description><![CDATA[<p>예전에 오픈랩 행사를 갔었는데, 교수님들 연구주제들 중에 <strong>군집 주행</strong>이 종종 등장했었다. 군집이란 단어를 들었었는데, 이게 다른 분야와 연관되어 사용될 수 있는 단어란 것을 알게 되었다.</p>
<p>지도 학습과 달리 레이블이 없는 비지도 학습! 그 중 먼저 군집에 대해 다루어 보려고 한다!</p>
<blockquote>
<p>군집? 일단 헤쳐 모여!</p>
</blockquote>
<p>데이터 분석, 고객 분류, 추천 시스템, 검색 엔진, 이미지 분할, 준지도 학습, 차원 축소 등에 활용할 수 있는 도구로, 비슷한 샘플을 클러스터로 모은다.</p>
<blockquote>
<p>K-평균의 특징?</p>
</blockquote>
<p>장점은 너~무 많다. 속도도 빠르지, 확장도 용이하지... 하지만 완벽한 것은 없다!</p>
<blockquote>
<p>클러스터의 크기 또는 밀집도가 서로 다르거나 원형이 아닌 경우
😋 작동 잘 안할게~를 시전한다고 함!</p>
</blockquote>
<h1 id="군집">군집</h1>
<p>군집은 비슷한 샘플을 구별해 하나의 cluster 또는 비슷한 샘플의 그룹으로 할당하는 작업을 의미한다.</p>
<p>분류 역시 샘플을 각 그룹에 할당하지만, 분류는 지도 학습이다. </p>
<p>군집은 어떻게 이용할 수 있을까?</p>
<ul>
<li>고객 분류 → 추천 시스템 만들기 가능</li>
<li>데이터 분석 → 군집 분석 선행 후 각 클러스터 분석</li>
<li>차원 축소 기법 → 각 클러스터에 대한 샘플의 친화성(affinity)측정 가능</li>
<li>특성 공학 → 클러스터 친화성 자체를 추가적인 특성으로 활용 가능</li>
<li>이상치 탐지 → 모든 클러스터에 친화성 ↓, 이상치일 확률이 높음!</li>
<li>준지도 학습 → 레이블된 샘플이 적다면 군집 후 동일 클러스터에 있는 모든 샘플에 레이블 전파 가능</li>
<li>검색 엔진 → 일부 검색 엔진은 제시된 이미지와 비슷한 이미지를 찾아줌</li>
<li>이미지 분할 → 이미지에 있는 색상의 수를 줄이면서 물체의 윤곽 감지 용이하게 만듦 → 물체 탐지 및 추적 시스템에 이용</li>
</ul>
<blockquote>
<p>클러스터 감지</p>
</blockquote>
<ul>
<li>센트로이드(centroid)라 부르는 특정 포인트를 중심으로 모인 샘플을 찾기</li>
<li>샘플이 밀집되어 연속된 영역 찾기</li>
</ul>
<h1 id="1-k-평균">1) k-평균</h1>
<ul>
<li>k-평균은 반복 몇 번으로 데이터셋을 빠르고 효율적으로 클러스터로 묶어주는 알고리즘</li>
<li>1957년 벨 연구소에서 스튜어트 로이드가 펄스 부호 변조 기법으로 제안한 내용, 하지만 1982년에 공개...</li>
<li>1965년에 에드워드 포지가 사실상 동일한 알고리즘 발표</li>
</ul>
<blockquote>
<p>그럼 사이좋게 이름 붙이자 : k-평균 = 로이드-포지 알고리즘</p>
</blockquote>
<p>k-평균 알고리즘은 센트로이드까지의 거리를 고려하는 것이 전부이기에, 클러스터의 크기가 많이 다르면 잘 작동하지 않음!</p>
<p>→ 따라서 소프트 군집이 유용할 수 있음!</p>
<blockquote>
<p>하드 군집 vs 소프트 군집</p>
</blockquote>
<p>하드 군집 : 샘플을 하나의 클러스터에 할당
소프트 군집 : 클러스터마다 샘플에 점수를 부여</p>
<ul>
<li>소프트 군집에서 점수는 가우스 방사 기저 함수와 같은 유사도 점수(similarity score) 또는 친화성 점수가 될 수 있다!</li>
</ul>
<blockquote>
<p>근데 이건 어떻게 작동하는 걸까?</p>
</blockquote>
<p>👏🏻짠! 센트로이드가 주어졌지롱
모든 샘플에 가장 가까운 센트로이드의 클러스터 할당</p>
<p>👏🏻짠! 샘플의 레이블이 모두 주어졌지롱
각 클러스터에 속한 샘플의 평균 계산 하여 센트로이드 구하기</p>
<p>👏🏻짠 ! 아무것도 없네?</p>
<ol>
<li>데이터셋에서 k개의 샘플을 뽑아 그 위치를 센트로이드로 지정</li>
<li>샘플에 레이블 할당</li>
<li>센트로이드 업데이트</li>
<li>2,3을 수렴할 때 까지 반복!</li>
</ol>
<blockquote>
<p>😗 그런데 수렴이 언제 끝날 줄 알고...?</p>
</blockquote>
<p>→ 샘플과 가장 가까운 센트로이드 사이의 평균 제곱 거리는 각 단계마다 내려갈 수만 있고, 음수가 될 수 없기에 수렴을 보장한다고 함! 따라서 제한된 횟수 안에 수렴하는 것이 보장됨!</p>
<blockquote>
<p>🤔 수렴은 보장되지만 적절한 솔루션이 된다고 얘기는 안 했다...</p>
</blockquote>
<p>지역 최적점으로 수렴하면 말짱 꽝!</p>
<h1 id="2-센트로이드-초기화-방법">2) 센트로이드 초기화 방법</h1>
<blockquote>
<p>저 센트로이드 위치 알아요...! 근사지만!!</p>
</blockquote>
<p><strong>가자 랜덤~!</strong>
랜덤 초기화를 다르게 하여 여러번 알고리즘 실행하여 가장 좋은 솔루션을 선택할 수도 있다. </p>
<p><strong><em>그런데 최선의 솔루션은 어떻게 찾아야할까?</em></strong>
최선의 솔루션을 보는 성능 지표는 모델의 <strong>&#39;이너셔(inertia)`</strong>다.
이 값은 각 샘플과 가장 가까운 센트로이드 사이의 제곱 거리 합이다.</p>
<h3 id="k-평균알고리즘">k-평균++알고리즘</h3>
<blockquote>
<p>2006년 논문, by David Arthur &amp; Sergei Vassilvitskii</p>
</blockquote>
<ul>
<li>다른 센트로이드와 거리가 먼 센트로이드를 선택하는 초기화 단계를 소개</li>
<li>최적의 솔루션으로 수렴할 수 있도록 해주기에 이 과정에서 들어가는 계산은 충분히 할 가치가 있음!</li>
</ul>
<ol>
<li><p>데이터셋에서 랜덤으로 균등하게 하나의 센트로이드 선택 $\bf c^{(1)}$</p>
</li>
<li><p>$$
\frac{D(x^{(i)})^2}{\sum_{j=1}^{n} D(x^{(j)})^2}$$
위의 확률로 샘플 $\bf x^{(1)}$를 새로운 센트로이드 $\bf c^{(1)}$로 선택
$D(\bf x^{(1)})$ : 샘플 $\bf x^{(1)}$와 이미 선택된 가장 가까운 센트로이드까지 거리
이 확률 분포 자체는 이미 선택한 센트로이드에서 멀리 떨어진 샘플을 다음 센트로이드로 선택할 가능성을 높임.</p>
</li>
<li><p>$k$개의 센트로이드가 선택될 때까지 이전 단계 반복</p>
</li>
</ol>
<h1 id="3-k-평균-속도-개선--미니배치-k-평균">3) k-평균 속도 개선 &amp; 미니배치 k-평균</h1>
<blockquote>
<p>2013년 Charles Elkan 논문</p>
</blockquote>
<p><em><strong>&quot;클러스터가 많은 일부 대규모 데이터셋에서 불필요한 거리 계산을 피함으로써 알고리즘의 속도를 상당히 높일 수 있다!&quot;</strong></em></p>
<p>이용한 것</p>
<ol>
<li>삼각 부등식(triangle inequality, AC ≤ AB + BC) 사용
(두 점 사이의 직선은 항상 가장 짧은 거리가 된다는 것 이용)</li>
<li>샘플-센트로이드 사이의 거리는 하한선과 상한선 유지</li>
</ol>
<p>다만❗항상 알고리즘이 훈련 속도를 높이는 것은 아님! 때로는 훈련 속도가 상당히 느려질 수도 있음!</p>
<blockquote>
<p>2010년 David Sculley</p>
</blockquote>
<p>방식 : 전체 데이터셋을 사용해 반복하지 않고 <strong>각 반복마다 미니배치</strong>를 사용해 센트로이드를 조금씩 이동</p>
<p>→ 알고리즘의 속도를 3~4배 정도 높이는 것 가능
→  메모리에 들어가지 않는 대량의 데이터셋에 군집 알고리즘을 적용 가능</p>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>일반 K-평균 알고리즘</strong></th>
<th><strong>미니 배치 K-평균 알고리즘</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>데이터 처리 방식</strong></td>
<td>전체 데이터셋을 한 번에 사용</td>
<td>데이터셋에서 일부 샘플(미니 배치)을 반복적으로 사용</td>
</tr>
<tr>
<td><strong>수렴 속도</strong></td>
<td>비교적 느림</td>
<td>더 빠르게 수렴</td>
</tr>
<tr>
<td><strong>메모리 사용량</strong></td>
<td>데이터셋 크기에 따라 높음</td>
<td>미니 배치 크기에 따라 낮음</td>
</tr>
<tr>
<td><strong>복잡도</strong></td>
<td>데이터 크기에 비례 ((O(n \cdot k \cdot t)))</td>
<td>미니 배치 크기에 비례 ((O(b \cdot k \cdot t)))</td>
</tr>
<tr>
<td><strong>결과 품질</strong></td>
<td>일반적으로 더 높은 클러스터링 품질</td>
<td>품질이 다소 낮을 수 있음</td>
</tr>
<tr>
<td><strong>적합한 데이터 크기</strong></td>
<td>작은 데이터셋에 적합</td>
<td>대규모 데이터셋에 적합</td>
</tr>
<tr>
<td><strong>온라인 학습</strong></td>
<td>지원하지 않음</td>
<td>지원 가능</td>
</tr>
</tbody></table>
<h1 id="4-최적의-클러스터">4) 최적의 클러스터</h1>
<p>클러스터 개수는 어떻게 정할까?</p>
<blockquote>
<p>가장 작은 inertia를 선택하는 것은?</p>
</blockquote>
<p>k ↑ inertia ↓
따라서 k 선택 시 inertia는 좋은 성능 지표가 아님.</p>
<p>클러스터 ↑ 각 샘플은 가까운 센트로이드에 더 가까워져서 inertia 작아짐</p>
<blockquote>
<p>그럼 어떻게 정하라고?
<strong><em>&quot;실루엣 점수 silhouette scroe&quot; 이용하자!</em></strong></p>
</blockquote>
<p>정확하지만 계산 비용은 많이 들어간다...<del>등골이 휘어요</del></p>
<p>실루엣 점수 : 모든 실루엣 계수의 평균
샘플의 실루엣 계수 :
$$
\frac{b-a}{max(a,b)}$$</p>
<p>$a$ : 클러스터 내부의 평균 거리(동일한 클러스터에 있는 다른 샘플까지 평균 거리)
$b$ : 가장 가까운 클러스터까지 평균 거리 (가장 가까운 클러스터의 샘플까지 평균 거리. 샘플과 가장 가까운 클러스터는 자신이 속한 클러스터를 제외하고 b가 최소인 클러스터)</p>
<p><strong>실루엣 계수 범위</strong> : -1~+1</p>
<p><strong>+1에 가까움 *<em>:  자신의 클러스터 안에 잘 속해 있지만, 다른 클러스터와는 멀리 떨어져 있음.
*</em>0에 가까움</strong> : 클러스터 경계에 위치
<strong>-1에 가까움</strong> :  샘플이 잘못된 클러스터에 할당</p>
<blockquote>
<p>모든 샘플의 실루엣 계수를 할당된 클러스터와 계수 값으로 정렬하여 그리면 더 많은 정보를 얻을 수 있는데, 이게 바로 <strong>실루엣 다이어그램(silhouette diagram)</strong></p>
</blockquote>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/97c6e3c6-99b4-4348-97f1-b3bdeb6e436c/image.png" width = 80% disply =block margin = 4> </p>



<p>그래프 높이 : 클러스터가 포함하고 있는 샘플의 개수
그래프 너비 : 클러스터에 포함된 샘플의 정렬된 실루엣 계수(넓을수록 좋음)
수직 파선 :  각 클러스터 개수에 해당하는 평균 실루엣 점수</p>
<ul>
<li>많은 샘플이 파선의 왼쪽에서 멈추면 나쁜 클러스터<ul>
<li>왜? 클러스터 샘플이 다른 클러스터랑 너무 가깝다는 뜻이니!</li>
</ul>
</li>
</ul>
<h1 id="5-군집을-이용한-이미지-분할">5) 군집을 이용한 이미지 분할</h1>
<blockquote>
<p>이미지 분할(image segmentation) = 이미지를 여러 개의 segment로 분할</p>
</blockquote>
<ul>
<li>색상 분할</li>
<li>시맨틱 분할</li>
<li>인스턴스 분할</li>
</ul>
<blockquote>
<p>시맨틱 분할과 인스턴스 분할에서 최고 수준의 성능을 내려면 CNN 기반의 복잡한 모델을 사용하는 것이 좋다!</p>
</blockquote>
<table>
<thead>
<tr>
<th>특징</th>
<th>색상 분할</th>
<th>시맨틱 분할</th>
<th>인스턴스 분할</th>
</tr>
</thead>
<tbody><tr>
<td><strong>목적</strong></td>
<td>색상 기반으로 영역 분리</td>
<td>클래스별로 픽셀 레이블링</td>
<td>개별 객체를 픽셀 단위로 구분</td>
</tr>
<tr>
<td><strong>기술적 난이도</strong></td>
<td>쉬움</td>
<td>중간</td>
<td>어려움</td>
</tr>
<tr>
<td><strong>결과</strong></td>
<td>특정 색상 영역 마스크 생성</td>
<td>클래스별 분할된 이미지</td>
<td>객체별로 분리된 이미지</td>
</tr>
<tr>
<td><strong>모델</strong></td>
<td>간단한 임계값 계산</td>
<td>U-Net, DeepLab 등</td>
<td>Mask R-CNN, SOLO 등</td>
</tr>
<tr>
<td><strong>응용 분야</strong></td>
<td>간단한 객체 탐지</td>
<td>자율 주행, 의료 영상</td>
<td>AR/VR, 로봇 비전</td>
</tr>
</tbody></table>
<p>k- 평균은 비슷한 크기의 클러스터를 만드는 경향이 있음.
→ 아무리 화려한 무늬를 가지더라도 k-평균이 하나의 클러스터로 만들지 못함.</p>
<h1 id="6-군집을-이용한-준지도-학습">6) 군집을 이용한 준지도 학습</h1>
<blockquote>
<p>사실상 전처리 하는 것이다!</p>
</blockquote>
<p>😗 언제 사용하지?
 →  레이블이 없는 데이터가 많고 레이블이 있는 데이터는 적을 때!</p>
<p>*<em>대표 이미지 *</em>: (representative image) 각 클러스터에서 센트로이드에 가장 가까운 이미지 찾기, 여기서 이 이미지가 대표 이미지</p>
<p><strong>레이블 전파</strong> : (label propagation) 랜덤 샘플대신 대표샘플에 레이블을 할당</p>
<p>클러스터 중심에서 먼 샘플 제거 : 일부 이상치 제거 → 정확도 향상</p>
<blockquote>
<p>능동 학습(active learning) - 불확실성 샘플링(uncertainty sampling)</p>
</blockquote>
<p>능동 학습 :  전문가가 학습 알고리즘과 상호 작용하여 알고리즘이 요청할 때 특정 샘플의 레이블을 제공</p>
<p><strong>&lt;불확실성 샘플링 작동 방식&gt;</strong></p>
<ol>
<li>지금까지 수집한 레이블된 샘플에서 모델을 훈련, 이 모델을 사용해 레이블되지 않은 모든 샘플에 대한 예측을 만들기
2, <strong>모델이 가장 불확실하게 예측한 샘플(즉, 추정 확률이 낮은 샘플)을</strong> 전문가에게 보내 레이블을 붙이기
3 레이블을 부여하는 노력만큼의 성능이 항상되지 않을 때까지 이를 반복</li>
</ol>
<p>다른 전략 : 모델을 가장 크게 바꾸는 샘플이나 모델의 검증 점수를 가장 크게 떨어뜨리는 샘플, 여러 개의 모델이 동일한 예측을 내지 않는 샘플에 대해 레이블 요청</p>
<h1 id="7-dbscan">7) DBSCAN</h1>
<blockquote>
<p>density-based spatial clustering of applications with noise</p>
</blockquote>
<p>여기서 클러스터 : 밀집된 연속적 지역</p>
<ol>
<li>알고리즘이 각 샘플에서 작은 거리인 ε 내에 샘플이 몇 개 놓여 있는지 세기
 a. 이 지역을 샘플의 ε-이웃 (ε-neighborhood)라고 부름</li>
<li>자기 자신을 포함해 ε-이웃 내에 적어도 <code>min_samples</code>개의 샘플이 있다면 이를 <strong>핵심 샘플(core instance)</strong>로 간주 → 즉 핵심 샘플 = 밀집된 지역에 있는 샘플</li>
<li>핵심 샘플의 이웃에 있는 모든 샘플 → 동일한 클러스터 (이 방법으로 하나의 클러스터 생성)</li>
<li>핵심 샘플X, 이웃 샘플 X → 이상치</li>
</ol>
<ul>
<li>모든 클러스터가 밀집되지 않은 지역과 구분될 때 좋은 성능 가능!</li>
<li>클러스터 모양과 개수에 상관없이 사용 가능</li>
<li>이상치에 안정적, 매개변수 2개(<code>eps</code>, <code>min_samples</code>)</li>
<li>클러스터 간의 밀집도가 크게 다르거나, 일부 클러스터 주변에 저밀도 영역이 충분히 없는 경우엔 클러스터 올바르게 잡기에 어려움 있을 수 있음.</li>
<li>계산 복잡도 : $O(m^2n)$ → 대규모 데이터셋 확장 잘 X</li>
</ul>
<h1 id="8-다른-군집-알고리즘">8) 다른 군집 알고리즘</h1>
<h3 id="병합-군집">병합 군집</h3>
<blockquote>
<p>agglomerative clustering</p>
</blockquote>
<p>반복마다 인접한 클러스터 쌍을 연결하여 트리를 만드는데,
이때 트리는 이진 트리가 된다. (트리의 leaf = 개별 샘플)</p>
<ul>
<li>다양한 형태의 클러스터 감지 가능</li>
<li>특정 클러스터 개수 선택에 도움이 되는 유용한 클러스터 트리 만들기 가능</li>
<li>짝 거리(pairwise distance)와도 사용 가능</li>
<li>이웃한 샘플 간의 거리를 담은 $m \times m$ 크기 희소 행렬을 연결 행렬로 전달하는 식으로 대규모 샘플에도 적용 가능</li>
</ul>
<p>단! 연결 행렬이 없으면 대규모 데이터셋으로 확장하기 어려움!</p>
<h3 id="birch">BIRCH</h3>
<blockquote>
<p>balanced iterative reducing and clustering using hierarchies</p>
</blockquote>
<ul>
<li>대규모 데이터셋을 위해 고안됨.</li>
<li>특성 개수가 너무 많지 않으면(20개 이하, 오 적은데) 배치 k-평균보다 빠르고 비슷한 결과를 만듦</li>
<li>훈련 과정에서 새로운 샘플을 클러스터에 빠르게 할당할 수 있는 정보를 담은 트리 구조를 만드는데, 이 트리에 모든 샘플을 저장하지는 않는다.</li>
<li>제한된 메모리를 사용하기에 대용량 데이터셋 다루기 가능</li>
</ul>
<h3 id="평균-이동">평균-이동</h3>
<ol>
<li>각 샘플을 중심으로 하는 원 그리기</li>
<li>원마다 안에 포함된 샘플의 평균 구하기</li>
<li>원의 중심을 평균점으로 이동</li>
</ol>
<p>→ 모든 원이 이동하지 않을 때까지 이러한 <strong>평균-이동(mean-shift)</strong> 반복</p>
<ul>
<li>동일한 지역에 안착한 원에 있는 모든 샘플은 동일한 클러스터가 됨!</li>
<li>DBSCAN과 유사한 특징이 있으나, 모양이나 개수 상관없이 클러스터 찾기 가능!</li>
<li>하이퍼파라미터 : 대역폭(bandwidth, 원 반경) 1개뿐! → 국부적인 밀집도 추정에 의존</li>
<li>클러스터 내부 밀집도가 불균형 → 클러스터를 여러 개로 나누느 경향 있음</li>
<li>계산 복잡도 : $O(m^2)$ → 대규모 데이터셋에 적합 X</li>
</ul>
<h3 id="유사도-전파">유사도-전파</h3>
<p><strong>예시(exemplar)</strong> 
이해가 안 가니까 예시로 기억하자...!</p>
<p>정치적인 상황에서는 나와 비슷한 의견을 가진 후보에게 투표하고 싶지만, 해당 당이 이기는 것이 더 우선이기에 더 인기 있는 후보를 선택할 수도 있다. </p>
<p>모든 샘플은 자신을 대표할 다른 샘플(데이터는 정치가 아니니까 자신도 포함!)을 ㅅ헌택할 때까지 샘플 간에 메시지를 반복적으로 교환하며, 이렇게 선출된 샘플이 <strong>예시</strong>다.</p>
<p>k-평균과 달리 미리 클러스터 수를 정할 필요가 없다. 훈련 중에 결정되기 때문이다. 하지만 k-평균과 유사하게 클러스터의 중심 근처에 위치한 예시를 선택하는 경향도 있다.</p>
<p>다양한 크기의 데이터 처리가 가능하지만, 계산 복잡도가 $O(m^2)$이라 대규모 데이터셋엔 적합하지 않다!</p>
<h3 id="스펙트럼-군집">스펙트럼-군집</h3>
<p>샘플 사이의 유사도 행렬을 받아서 저차원 임베딩 생성(행렬의 차원 축소)
→ 이 저차원 공간에서 또 다른 군집 알고리즘 사용(사이킷런은 k-평균 이용)</p>
<ul>
<li>복잡한 클러스터 구조 감지 가능</li>
<li>그래프 컷(graph cut) 찾는 데 이용 가능(=소셜 네트워크에서 친구의 클러스터 찾기 가능)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]8장 차원 타노스]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning8%EC%9E%A5-%EC%B0%A8%EC%9B%90-%ED%83%80%EB%85%B8%EC%8A%A4</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning8%EC%9E%A5-%EC%B0%A8%EC%9B%90-%ED%83%80%EB%85%B8%EC%8A%A4</guid>
            <pubDate>Mon, 18 Nov 2024 16:13:14 GMT</pubDate>
            <description><![CDATA[<p>매번 컬럼 많은 데이터만 나오는 우려먹는 얘기지만...LG Aimers 하면서 느꼈던 것... 우와 컬럼이 진짜 정말정말 많구나...!!<del>대체 얼마나 충격을 받았었으면</del></p>
<p>하지만 이렇게 많은 특성이 있으면 훈련을 느리게 할 뿐만 아니라 좋은 솔루션을 찾기 어렵다! 그래서 이런 문제를 <strong>차원의 저주(curse of dimensionality)</strong>라고 한다.</p>
<blockquote>
<p>실전에서는 특성 수를 줄여 불가능한 문제→가능한 범위로 변경 가능
ex) MNIST</p>
</blockquote>
<p>이미지 경계의 픽셀은 거의 흰색이기에, 이런 인접한 픽셀을 하나의 픽셀로 합치더라도 잃는 정보가 많지 않음!
→ 이렇게 하면 학습할 정보가 타노스 되었기에 훈련 속도를 높이는 것이 가능해진다. 또한 데이터 시각화에도 유용하다고 한다.(하나의 압축된 그래프를 그려 새로운 패턴을 찾을 수도 있다는 것!)</p>
<p><strong>차원 축소</strong>에 사용되는 두 가지 주요 접근 방법인</p>
<ul>
<li>투영(projection)</li>
<li>매니폴드(manifold learning)
를 정리해 보겠다.</li>
</ul>
<p>참고로 가장 인기 있는 차원 축소 기법 : PCA(주성분 분석), 랜덤 투영, 지역 선형 임베딩(<strong>l</strong>ocally <strong>l</strong>inear <strong>e</strong>mbedding)</p>
<h1 id="81-차원의-저주">8.1 차원의 저주</h1>
<ul>
<li>고차원 공간에 있다 
→ 데이터셋이 너무 많아서 훈련 데이터가 서로 <strong>멀리</strong> 떨어져 있게 된다.이런 경우 외삽(extrapolation)을 하게 되기에 저차원일 때보다 예측이 더 <strong>불안정</strong>해진다.</li>
</ul>
<blockquote>
<p>외삽(extrapolation)</p>
</blockquote>
<p>주어진 데이터 범위를 넘어 새로운 값을 예측하거나 추정하는 과정을 말한다. 이를 통해 이미 알고 있는 데이터의 패턴이나 관계를 기반으로, 데이터 범위 밖의 값을 추정할 수 있다.</p>
<p>차원의 저주를 해결하려면 훈련 샘플의 밀도가 충분히 높아질 때 까지 훈련 세트의 크기를 키워야 하지만 실제 이런 밀도에 도달하기 까지 위한 훈련 샘플 수는 기하급수적을 커지기에 사실상 <strong>불가능</strong>하다!</p>
<h1 id="82-차원-축소를-위한-접근법">8.2 차원 축소를 위한 접근법</h1>
<p>크게 두 가지가 있다. 위에서 언급했듯이 투영과 매니폴드다.</p>
<h2 id="1-투영-projection">1) 투영 (projection)</h2>
<p>흔히 선형대수에서 배웠던 그 투영을 생각하면 된다. 3차원 공간이 있다면 특정 평면에 대해 모두 수직으로 투영하는 것을 생각해주면 된다.</p>
<p>실전 문제에서 훈련 샘플은 모든 차원에 걸쳐 균일하게 퍼져 있지는 않기에 대부분의 훈련 샘플이 고차원 공간 안의 저차원 subspace에 위치하게 된다. (특정 특성은 거의 변화가 없지만, 일부 특성들이 강하게 연관되어 있기에 이런 결과가 나타난다.)</p>
<p>차원 축소에서 언제나 투영이 최선의 방법인 것은 아니다.
<strong>스위스 롤</strong>이 바로 그 예시다.</p>
<h2 id="2-매니폴드-manifold">2) 매니폴드 (manifold)</h2>
<p>스위스 롤은 2D 매니폴드의 한 예시다. 즉 2D 매니폴드는 고차원 공간에서 휘어지거나 뒤틀린 2D 모양이라는 것이다.</p>
<p>일반화해서 나타내면
→ d차원의 매니폴드는 d차원 초평면(hyperplane)으로 보일 수 있는 n차원 공간의 일부이다. (d&lt;n), 
→ 스위스롤에서 d = 2, n = 3 즉 국부적으로 2D평면으로 보이지만 3차원으로 말려있다는 것이다.</p>
<p>많은 축소 알고리즘이 훈련 샘프링 놓여 있는 manifold를 모델링하는 식드로 작동하며 이를 <strong>매니폴드 학습</strong> 이라고 한다! 대부분 실제 고차원 데이터셋이 더 낮은 저차원 매니폴드에 가깝게 놓여 있다는 매니폴드 가정(=매니폴드 가설)에 의거한다. 즉 대부분의 실전 문제는 훈련 샘플은 모든 차원에 걸쳐 균일하게 퍼져 있지는 않기에 대부분의 훈련 샘플이 고차원 공간 안의 저차원 subspace에 위치하게 된다는 특성을 이용한 거승로 보이며, 이는 경험적으로도 잘 맞는다고 한다!</p>
<p>좀 더 문제를 간단하게 하고자 암묵적으로 다른 가정과 병행되기도 한다.</p>
<ul>
<li>분류나 회귀가 이 저차원의 매니폴드 공간에 표현되면 더 간단해질 것</li>
</ul>
<p>다만 당연히 항상 암묵적 가정이 성립하는 것은 아니다...! 즉 모델 훈련 전에 세트의 차원을 감소시키면 훈련 속도는 빨라지는 것은 보자오디지만, 항상 더 낫거나 간단한 solution에는 도달하지 못할 수 있다는 것이다!</p>
<p><em>스위스롤 문제를 생각하면 어떤 방향으로 단면을 잘라야 잘 구분될 수 있는지를 생각해보면 좋을 것 같다...!</em></p>
<h1 id="83-주성분-분석-pca">8.3 주성분 분석 (PCA)</h1>
<blockquote>
<p>저차원으로 샘플들을 고르게 눌러서 투영해주어요~</p>
</blockquote>
<h2 id="1-주성분-분석-과정">1) 주성분 분석 과정</h2>
<ul>
<li><p>1) 분산 보존
훈련 세트를 투영하기 전에 올바른 초평면을 선택하는 것은 필수다! 결국 주성분 분석은 데이터를 잃는 과정이나 마찬가지다.</p>
</li>
<li><p>2) 주성분
훈련 세트에서 분산이 <strong>최대</strong>인 축을 차례로 찾기
→ $i$번째 축 = $i$번째 주성분(<strong>p</strong>rincipal <strong>c</strong>omponent)</p>
</li>
</ul>
<blockquote>
<p>훈련 세트의 주성분 찾는 방법</p>
</blockquote>
<p><strong>SVD</strong>, 특잇값 분해(singular value decomposition)를 이용하여 구하며, 이때 단위 벡터 V가 모든 주성분의 단위 벡터가 된다.</p>
<h3 id="numpy의-svd"><code>numpy</code>의 <code>svd()</code></h3>
<p><a href="https://numpy.org/doc/stable/reference/generated/numpy.linalg.svd.html">공식문서</a></p>
<pre><code class="language-python">linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)</code></pre>
<ul>
<li>3) $d$차원으로 투영
$d$개의 주성분 → 데이터셋을 $d$차원으로 축소 가능
이때 초평면은 분산을 가능한 범위 내에서 최대로 보존하는 투영(project)</li>
</ul>
<p>$$
\textbf{X}_{d-proj} = \textbf{X} \textbf{W}_d
$$</p>
<pre><code class="language-python">W2 = Vt[:2].T
X2D = X_centered @ W2</code></pre>
<h2 id="2-sklearn으로-pca하기">2) sklearn으로 PCA하기</h2>
<pre><code class="language-python">from sklearn.decomposition import PCA

pca = PCA(n_components=2)
X2D = pca.fit_transform(X)</code></pre>
<p>여기서 <code>components_</code>속성이 $\textbf{W}_d$
배열의 행은 처음 $d$개의 주성분에 해당</p>
<h3 id="3-설명된-분산의-비율">3) 설명된 분산의 비율</h3>
<blockquote>
<p>explained variance ratio
각 주성분의 축을 따라 있는 데이터셋의 분산 비율을 나타냄</p>
</blockquote>
<pre><code class="language-python">&gt;&gt;&gt; pca.explained_variance_ratio_
array([0.7578477J 0.15186921])</code></pre>
<p>→ 데이터셋 분산의 76%가 첫 번째 pc에 놓여 있고, 15%가 두 번째 pc를 따라 놓임
세 번째 pc에는 9%미만이 남아있을 것으로 보임. → 아주 적은 양의 정보</p>
<h3 id="4-적절한-차원-수-선택">4) 적절한 차원 수 선택</h3>
<p>기준 : 충분한 분산(예 : 95%)이 될 때까지 더해야 할 차원수 선택
<code>cumsum</code>을 그래프로 그리면 분산을 차원 수에 대한 함수로 그릴 수 있음.</p>
<ul>
<li>지도 학습의 전처리로 차원 축소 이용하는 경우<ul>
<li><code>RandomizedSearchCV</code>를 사용하여 PCA와 다른 학습 모델의 하이퍼파라미터 조합을 찾으면 됨.</li>
<li>이때 학습하는 다른 모델의 성능이 좋을 경우 필요한 차원 수가 많이 줄어들게 됨!</li>
</ul>
</li>
</ul>
<h3 id="5-압축을-위한-pca">5) 압축을 위한 PCA</h3>
<ul>
<li>압축된 데이터셋에 PCA 투영의 변환을 반대로 적용하면 다시 고차원으로 만들기 가능</li>
<li>단 이때 원본 데이터와 완전히 같은 것은 만들 수 없음(정보 유실)</li>
<li>원본 데이터 &amp; 재구성된 데이터 사이의 평균 제곱 거리 → <strong>재구성 오차(reconstruction error)</strong></li>
<li><code>inverse_transform()</code> method를 이용
&lt;원본의 차원 수로 되돌리는 PCA 역변환
$$
\textbf{X}<em>{recovered} = \textbf{X}</em>{d-proj}\textbf{W}_d^T
$$</li>
</ul>
<h3 id="6-랜덤-pca">6) 랜덤 PCA</h3>
<p><code>svd_solver = randomized</code> : sklearn은 랜덤 PCA라 부르는 확률적 알고리즘을 사용해 처음 $d$개의 주성분에 대한 근삿값을 빠르게 찾을 수 있음.</p>
<ul>
<li><p>알고리즘 계산 복잡도</p>
</li>
<li><p>SVD : $O(m \times n^2) + O(n^3)$</p>
</li>
<li><p>svd_solver : $O(m \times d^2) + O(d^3)$</p>
<h3 id="pca의-매개변수--svd_solver"><code>PCA</code>의 매개변수 : <code>svd_solver</code></h3>
<p><a href="https://scikit-learn.org/dev/modules/generated/sklearn.decomposition.PCA.html"> PCA 공식 sklearn 문서</a></p>
<pre><code class="language-python">PCA(n_components=None, *, copy=True, whiten=False, svd_solver=&#39;auto&#39;, 
tol=0.0, iterated_power=&#39;auto&#39;, n_oversamples=10, 
power_iteration_normalizer=&#39;auto&#39;, random_state=None)</code></pre>
<pre><code class="language-python">svd_solver{‘auto’, ‘full’, ‘covariance_eigh’, ‘arpack’, ‘randomized’}, default=’auto’
“auto”</code></pre>
</li>
<li><p>기본값: ‘auto’</p>
</li>
<li><p>입력 데이터 $\textbf{X}$의 특성과 추출하려는 주성분 개수($n_components$)에 따라 나뉨</p>
</li>
<li><p><code>covariance_eigh</code> solver</p>
<ul>
<li>데이터가 <strong>특징 개수(열)</strong>가 1000개 미만이고, <strong>샘플 수(행)</strong>가 특징 개수의 10배 이상인 경우</li>
<li>데이터의 공분산 행렬을 계산하고, 고유값 분해(eigh)를 사용해 주성분을 계산</li>
<li>작은 데이터에서 효율적</li>
</ul>
</li>
<li><p><code>randomized</code> solver</p>
<ul>
<li>데이터 크기 500 X 500 이상, 추출하려는 주성분 개수가 데이터의 가장 작은 차원의 80%미만인 경우</li>
<li>랜덤화된 SVD(Singular Value Decomposition) 알고리즘을 사용</li>
<li>대규모 데이터에서 빠르고 효율적</li>
</ul>
</li>
<li><p><code>full</code> SVD solver</p>
<ul>
<li>위의 두 조건을 만족하지 않는 경우, 정확한 SVD 알고리즘이 수행</li>
<li>데이터의 모든 특성을 활용하며, 필요하면 결과를 축소</li>
<li>계산 비용이 높지만 가장 정확한 결과를 제공</li>
</ul>
</li>
</ul>
<h3 id="7-점진적-pca">7) 점진적 PCA</h3>
<ul>
<li><p>기존 PCA 구현의 문제점
  → SVD 알고리즘 실행을 위해 전체 훈련 세트를 메모리에 올려야 함.
  → <strong>점진적 PCA(incremental PCA, IPCA)</strong> 알고리즘 개발</p>
</li>
<li><p><strong>점진적 PCA(incremental PCA, IPCA)</strong></p>
<ul>
<li>훈련 세트를 미니배치로 나눔 </li>
<li>IPCA 알고리즘에 한 번에 하나씩 주입 </li>
<li>훈련 세트가 클수록 유리하고, 온라인(실시간으로 데이터가 주입되는 환경)에서도 PCA 적용 가능</li>
</ul>
</li>
<li><p>다만 매우 고차원 데이터셋인 경우, PCA가 너무 느려질 수 있음.
→ 수만 개 이상의 특성이 있다면 랜덤 투영을 사용하는 것을 고려해야 함</p>
<h3 id="incrementalpca"><code>IncrementalPCA</code></h3>
<p><a href="https://scikit-learn.org/dev/modules/generated/sklearn.decomposition.IncrementalPCA.html"> 함수 사용법</a></p>
<pre><code class="language-python">IncrementalPCA(n_components=None, *, whiten=False, copy=True, batch_size=None)</code></pre>
</li>
<li><p>개요</p>
<ul>
<li>데이터 선형 차원 축소를 위해 SVD 사용</li>
<li>가장 중요한 특이 벡터만 유지하여 데이터를 저차원 공간으로 투영</li>
<li>데이터는 중심화(mean centering)되지만, 특징 스케일링(scaling)은 적용 X</li>
</ul>
</li>
<li><p><strong>희소 데이터(sparse data)지원</strong></p>
<ul>
<li>희소 행렬을 처리할 수 있으며, 필요시 배치 단위로 밀집 행렬(dense matrix)로 변환</li>
</ul>
</li>
<li><p>상수 메모리 복잡도
: $O(batch_size \times n_features)$</p>
<ul>
<li>데이터 전체를 메모리에 로드하지 않아도 되기에 <code>np.memmap</code> 파일과 같은 메모리 매핑 기법을 사용해 큰 파일을 효율적으로 처리 가능</li>
</ul>
</li>
<li><p>희소 행렬 처리</p>
<ul>
<li>입력 희소 행렬은 배치 단위로 밀집 행렬로 변환 → 평균값을 계산하기 위해 필요</li>
<li>위의 과정은 전체 밀집 행렬을 저장하지 않고 처리</li>
</ul>
</li>
<li><p>IPCA에서 SVD 연산복잡도
: $O(batch_size \times n_features^2)$</p>
<ul>
<li>이때 메모리에 저장되는 샘플은 최대 배치 사이즈의 2배(개)로 제한</li>
</ul>
</li>
<li><p>전체 데이터셋에서 IPCA가 수행해야 하는 SVD 개수
: n_samples / batch_size</p>
</li>
<li><p>: PCA에서 사용하는 큰 크기의 SVD 연산($O(샘플개수 \times 특성개수^2)$)과 비교하면 효율적</p>
</li>
</ul>
<h3 id="memmap"><code>memmap</code></h3>
<p><a href="https://numpy.org/doc/stable/reference/generated/numpy.memmap.html"> numpy memmap</a></p>
<pre><code class="language-python">memmap(filename, dtype=&lt;class &#39;numpy.ubyte&#39;&gt;, mode=&#39;r+&#39;, offset=0, shape=None, order=&#39;C&#39;)</code></pre>
<ul>
<li>역할<ul>
<li>디스크에 저장된 큰 이진 파일을 직접 메모리에서 다루는 것처럼 사용할 수 있도록 만들어줌</li>
<li>전체 파일을 메모리에 로드하지 않고, 필요한 부분만 메모리에 맵핑하여 작업</li>
<li>RAM이 부족한 상황에서 대규모 데이터를 처리할 때 유용</li>
</ul>
</li>
</ul>
<h1 id="84-랜덤-투영">8.4 랜덤 투영</h1>
<blockquote>
<p>랜덤 투영은 간단하고 빠르고 메모리 효율이 높음!! 특히 고차원 데이터셋엥 아주아주 유용함!! 뿐만 아니라 검색 엔진에서 유사한 문서를 그룹화하는데 사용되는 LSH(locality sensitive hashing) 알고리즘과 유사</p>
</blockquote>
<ul>
<li>선형 투영을 사용하여 데이터를 저차원 공간에 투영
  →  실제로 기존 샘플들 간의 거리를 상당히 잘 보존할 가능성이 매우 높음<ul>
<li>William B.Johnson과 Joram Lindenstrauss가 수학적으로 증명해냄</li>
</ul>
</li>
<li>더 처차원으로 갈수록 더 많은 정보가 손실되고 더 많은 거리가 왜곡 
→ 최적의 차원을 고르는 방법은?&gt;<ul>
<li>William B.Johnson과 Joram Lindenstraussdl이 고안한 방정식 이용
→ <code>johnson_lindenstrauss_min_dim()</code> 함수에 구현되어 있음!</li>
</ul>
</li>
</ul>
<h3 id="johnson_lindenstrauss_min_dim"><code>johnson_lindenstrauss_min_dim()</code></h3>
<p>만약</p>
<ul>
<li><p>$n=20,000$, $n$은 특성</p>
</li>
<li><p>$m=5,000$, $m$은 샘플 개수</p>
</li>
<li><p>두 샘플 간의 제곱 거리가 를 초과하여 변경되지 않도록 하려면 제곱 거리가 ε = 10%를 변경되지 않도록 데이터를 7,300개 차원으로 투영해야 함.
$$
d \geq \frac{4\log(m)}{½ε^2 - ⅓ε^3}
$$
이 방정식을 보면 m과 ε에 의존하며, n에는 의존하지 않는다는 것을 알 수 있음.</p>
</li>
<li><p>평균 : 0, 분산 : 1/d의 가우스 분포에서 랜덤 샘플링한 $[d,n]$ 크기의 랜덤 행렬 $\textbf P$를 생성하고 이를 사용하여 데이터셋을 $n$차원에서 $d$차원으로 투영할 수 있음.</p>
</li>
<li><p>→알고리즘이 랜덤한 행렬을 생성하는 데 필요한 것 : 데이터셋의 크기(데이터 자체 이용 X)</p>
</li>
</ul>
<h3 id="sklearn의-gaussianrndomprojection"><code>sklearn</code>의 <code>GaussianRndomProjection</code></h3>
<ul>
<li>위의 함수와 같은 역할을 함.</li>
<li>step 1) <code>fit()</code> : <code>johnson_lindenstrauss_min_dim()</code>사용해 출력 차원 결정, 랜덤한 행렬 생성하여 <code>components_</code> 속성에 저장</li>
<li>step 2) <code>transform()</code> : step 1)에서 만든 행렬 사용하여 투영 수행</li>
<li>이때 ε을 조정하려면 <code>eps</code>를 설정하고 특정 차원 $d$를 강제로 적용하려면 <code>n_components</code>를 설정해야함.</li>
</ul>
<h3 id="sklearn의-sparserndomprojection"><code>sklearn</code>의 <code>SparseRndomProjection</code></h3>
<ul>
<li><p><code>GaussianRndomProjection</code>와 step 1), step 2) 과정이 똑같이 작용하지만, 랜덤 행렬의 <strong>희소</strong>하다는 차이점이 존재
→ 메모리를 더 적게 활용할 수 있음.(속도도 향상 시킬 수 있음)</p>
</li>
<li><p>입력이 희소 → 변환은 희소성을 유지(<code>dense_output-True</code>로 설정 X 경우)</p>
</li>
<li><p><code>GaussianRndomProjection</code>와 동일한 거리 보존 속성을 가지며 차원 축소 품질도 비슷
→ &lt;규모가 크거나 희박한 데이터셋&gt;인 경우 <code>SparseRndomProjection</code> 쓰는 것이 더 바람직</p>
</li>
<li><p>밀도(density) : 희소한 랜덤 행렬에서 0이 아닌 항목의 비율 $r$</p>
<ul>
<li>기본적으로 밀도는 $\frac{1}{\sqrt{n}}$</li>
</ul>
</li>
<li><p>원하는 경우 <code>density</code> 매개변수를 이용하여 다른 값으로 설정 가능</p>
<ul>
<li><p>희소 랜덤 행렬의 각 항목이 0이 아닐 확률 $r$</p>
</li>
<li><p>희소 랜덤 행렬의 각 항목이 0일 확률 $-v$ 또는 $+v$ ←둘 다 동일 확률</p>
</li>
<li><p>여기서 $v = \frac{1}{\sqrt{dr}}$</p>
</li>
<li><p>역변환 수행 필요</p>
<ul>
<li>사이파이의 <code>pinv()</code> 함수 이용하여 성분 행렬의 유사역행렬 계산 후, 축소된 데이터에 유사역행렬의 전치를 곱해야 함.<ul>
<li><code>pinv()</code>의 계산 복잡도</li>
<li>$d &lt; n$일 경우 : $O(dn^2)$</li>
<li>$d \geq n$일 경우 : $O(nd^2)$</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="85-지역-선형-임베딩">8.5 지역 선형 임베딩</h1>
<blockquote>
<p>locally linear embedding(LLE)
<strong>비선형 차원 축소(NLDR)</strong> 기술임.(nonlinear dimensionality reduction)</p>
</blockquote>
<ul>
<li>투영에 의존하지 않는 매니폴드 학습<ul>
<li>step 1) 각 훈련 샘플이 최근점 이웃에 얼마나 선형적 연관되어 있는지 측정</li>
<li>step 2) 국부적인 관계가 가장 잘 보존되는 훈련 세트의 전차원 표현 찾기<ul>
<li>참고로 이 방법은 noise가 너무 많지 않은 경우, 꼬인 매니폴드 펼칠 때 좋음.</li>
</ul>
</li>
</ul>
</li>
<li><code>sklearn</code>의 <code>LocallyLinearEmbedding</code> 이용 가능</li>
</ul>
<h3 id="sklearn의-locallylinearembedding"><code>sklearn</code>의 <code>LocallyLinearEmbedding</code></h3>
<p><a href="https://scikit-learn.org/1.5/modules/generated/sklearn.manifold.LocallyLinearEmbedding.html">공식 문서</a></p>
<pre><code class="language-python">class sklearn.manifold.LocallyLinearEmbedding(*, n_neighbors=5, 
n_components=2, reg=0.001, eigen_solver=&#39;auto&#39;, tol=1e-06, 
max_iter=100, method=&#39;standard&#39;, hessian_tol=0.0001, modified_tol=1e-
12, neighbors_algorithm=&#39;auto&#39;, random_state=None, n_jobs=None)</code></pre>
<p>변수 t : 스위스 롤의 회전 축을 따라 각 샘플의 위치를 포함하는 1D 넘파이 배열
→ 비선형 회귀 작업의 타깃으로 이용 가능
이용하게 되면 샘플 간 거리가 잘 유지되지 않고, 펼쳐진 스위스 롤은 늘어나거나 꼬인 밴드가 아니라 직사각형이 된다. 그럼에도 불구하고 LLE는 매니폴드를 모델링할 때 잘 작동함!</p>
<h3 id="작동-원리">작동 원리</h3>
<ul>
<li>step 1) 알고리즘이 각 훈련 샘플 $\textbf{x}^{(i)}$에 대해 k개의 최근접 이웃 찾기</li>
<li>step 2) 이웃에 대한 선형 함수로 $\textbf{x}^{(i)}$ 재구성<ul>
<li>$\textbf{x}^{(i)}$와 $\sum ^m <em>{j=1} w_i\textbf{x}^{(i)}$ 사이의 <strong>제곱 거리</strong>가 최소가 되는 $w</em>{ij}$를 찾는 것</li>
<li>만약 $\textbf{x}^{(i)}$가 $\textbf{x}^{(i)}$의 가장 가까운 $k$개 이웃 중 하나가 아닐 경우엔 $w_{ij}=0$이 됨.</li>
</ul>
</li>
</ul>
<blockquote>
<p>LLE 단계 1: 선형적인 지역 관계 모델링 
같은 제한이 있는 최적화 문제가 되어 아래와 같이 식을 작성할 수 있다.</p>
</blockquote>
<p>$\textbf{W}$ : 가중치 $w_{i,j}$를 담은 가중치 행렬
두 번째 제약 : 각 훈련 샘플 $\textbf{x}^{(i)}$에 대한 가중치를 단순히 정규화하는 것</p>
<p>$$
\hat{\mathbf{W}} = \arg\min_{\mathbf{W}} \sum_{i=1}^{m} \left( \mathbf{x}^{(i)} - \sum_{j=1}^{m} w_{i,j} \mathbf{x}^{(j)} \right)^2
$$
$$
\begin{cases} 
w_{i,j} = 0 &amp; \text{만약 } \mathbf{x}^{(j)} \text{가 } \mathbf{x}^{(i)} \text{의 최근접 이웃 } k \text{개 중 하나가 아닐 때} \
\sum_{j=1}^{m} w_{i,j} = 1 &amp; \text{for } i = 1, 2, \dots, m
\end{cases}$$</p>
<p>위의 단계를 거치면 $\hat {W_{i,j}}$가 모인 가중치 행렬 $\hat{\textbf{W}}$은 훈련 샘플 사이에 있는 지역 선형 관계를 담게 된다.</p>
<ul>
<li><p>step 3) 가능한 한 이 지역 선형 관계가 보존되도록 훈련 샘플을 $d$차원 공간 ($d$ &lt; $n$)으로 매핑해야함. </p>
</li>
<li><p>만약 $\textbf{z}^{(i)}$가 $d$차원 공간에서  $\textbf{x}^{(i)}$의 상(image)라면 가능한 한  $\textbf{z}^{(i)}$와 $\sum_{j=1}^{m} \hat{w}_{i,j} \mathbf{z}^{(j)})^2$ 사이의 거리가 최소화 되어야 한다.
→ 제약이 없는 최적화 문제가 된다.</p>
</li>
</ul>
<blockquote>
<p>LLE 단계 2: 관계를 보존하는 차원 축소 
$$
\hat{\mathbf{Z}} = \arg\min_{\mathbf{Z}} \sum_{i=1}^{m} \left( \mathbf{z}^{(i)} - \sum_{j=1}^{m} \hat{w}_{i,j} \mathbf{z}^{(j)} \right)^2$$</p>
</blockquote>
<ul>
<li>첫 번째 단계 : 샘플을 고정하고 최적의 가중치 찾기</li>
<li>두 번째 단계 : 가중치를 고정하고 저차원의 공간에서 샘플 이미지의 최적 위치 찾기</li>
<li>이때 $\mathbf{z}$는 모든 $\textbf{z}^{(i)}$를 포함하는 행렬</li>
</ul>
<h3 id="sklearn의-lle-구현"><code>sklearn</code>의 LLE 구현</h3>
<ul>
<li>계산 복잡도<ul>
<li>$k$개의 최근접 이웃 찾기 : $O(m \log (m) n\log(k))$</li>
<li>가중치 최적화 : $O(mnk^3)$</li>
<li>저차원 표현 만들기 : $O(dm^2)$</li>
</ul>
</li>
</ul>
<blockquote>
<p>정리!</p>
</blockquote>
<ul>
<li>마지막 항의 $m^2$ 때문에 대규모 데이터셋에 알고리즘 적용이 어려움.</li>
<li>LLE는 투영 기법과는 상당히 다르며 훨씬 더 복잡하지만 데이터가 비선형인 경우 훨씬 더 나은 저차원 표현 구성 가능!</li>
</ul>
<h1 id="86-다른-차원-축소-기법">8.6 다른 차원 축소 기법</h1>
<blockquote>
<p><code>sklearn</code>에서 제공하는 몇 가지 인기 차우너 축소 기법들</p>
</blockquote>
<ul>
<li><strong>다차원 스케일링(multidimensional scaling, MDS)</strong><ul>
<li>샘플 간의 거리 보존하면서 차원 축소</li>
<li>랜덤 투영은 고차원 데이터에는 적합하지만 저차원 데이터에서 잘 작동 X</li>
<li>전체 곡률을 유지하면서 스위스 롤을 평평하게 만듦</li>
</ul>
</li>
<li><strong>Isomap</strong><ul>
<li>step 1) 각 샘플을 가장 가깡누 이웃과 연결하는 식으로 그래프 생성</li>
<li>step 2) 샘플 간의 <strong>지오데식 거리(geodesic distance)</strong>를 유지하면서 차원 축소<ul>
<li>그래프 두 노드 사이의 지오데식 거리 = 두 노드 사이의 최단 경로를 이루는 노드의 수</li>
</ul>
</li>
<li>스위스롤의 곡률을 완전히 없앰.<ul>
<li>후속 작업에 따라 거시적인 구조를 보존하는 것이 좋을 수도 있지만, 나쁠 수도 있음.</li>
</ul>
</li>
</ul>
</li>
<li><strong>t-SNE(t-distributed stochastic neighbor embedding)</strong><ul>
<li>비슷한 샘플 → 가까이, 안 비슷한 샘플 → 멀리 떨어지도록 차원 축소</li>
<li>주로 시각화에 많이 이용되며, 특히 고차원 공간에 있는 샘플의 군집 시각화에 이용<ul>
<li>t-SNE를 사용하여 MNIST 이미지의 2D 맵 그리기 가능</li>
</ul>
</li>
<li>스위스 롤을 평평하게 만들고, 약간의 곡률을 보존하는 합리적인 작업 수행 → 클러스터 강조시키기 위해 롤을 분해 (후속 작업을 잘하면 좋을 수도 있음)</li>
</ul>
</li>
<li><strong>선형 판별 분석(linear discriminant analysis, LDA)</strong><ul>
<li>선형 분류 알고리즘</li>
<li>훈련 과정에서 클래스 사이를 가장 잘 구분하는 축을 학습<ul>
<li>축 → 데이터가 투영되는 초평면을 정의하는 데 이용 가능</li>
</ul>
</li>
<li>투영을 통해 가능한 한 클래스를 멀리 떨어지게 유지시키기에 LDA만으로 충분하지 않으면 다른 분류 알고리즘을 적용하기 전에 차원을 축소시키기에 좋음.</li>
</ul>
</li>
</ul>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/c0e57b72-8bf9-4498-bb5d-8282995bdc76/image.png" width = 80% disply =block margin = 4> </p>
PCA는 최대한 선(초평면) 안에 많은 데이터가, 선형 분류는 이렇게 한 선 안에서 데이터가 나누어질 수 있도록 하는 것을 목적으로 한다고 보면 된다.

<p><a href="https://www.youtube.com/watch?v=M4HpyJHPYBY">사진 출처 </a>: 캡쳐</p>
<p>PCA의 성능이 이렇게 뛰어난 줄 몰랐다. 특히 선형 판별 분석...전에 열심히 했는데 잊어버리기 전에 정리해야겠다. 피셔의 선형 판별 기다려라...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]7장 앙상블 학습과 랜덤 포레스트]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning7%EC%9E%A5-%EC%95%99%EC%83%81%EB%B8%94-%ED%95%99%EC%8A%B5%EA%B3%BC-%EB%9E%9C%EB%8D%A4-%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning7%EC%9E%A5-%EC%95%99%EC%83%81%EB%B8%94-%ED%95%99%EC%8A%B5%EA%B3%BC-%EB%9E%9C%EB%8D%A4-%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Mon, 11 Nov 2024 16:57:44 GMT</pubDate>
            <description><![CDATA[<p>드디어! 캐글 단골 소재 앙상블에 대해 알아보는 시간이다! 바로 가보자~</p>
<blockquote>
<p>✅ 앙상블(ensemble)</p>
</blockquote>
<p>앙상블은 일련의 예측기, 즉 여러 예측기(모델)를 모아둔 것으로 보면 된다! 그래서 여러 모델을 이용해서 예측을 하기에 앙상블 학습(ensemble learning), 앙상블 학습 알고리즘을 앙상블 방법(ensemble method)라고 한다!</p>
<p>앙상블을 방법을 이용하여 괜찮은 예측기를 연결하면 더 성능 좋은 예측기를 만들 수 있다고 한다. 그 중 인기있는 앙상블 방법을 다룬다.</p>
<ul>
<li>투표 기반 분류기</li>
<li>배깅과 페이스팅 앙상블</li>
<li>랜덤 포레스트</li>
<li>부스팅</li>
<li>스태킹 양상</li>
</ul>
<h1 id="71-다수결-투표-기반-분류기">7.1 다수결! 투표 기반 분류기</h1>
<ul>
<li>직접 투표(hard voting) : 예측값 바로 이용, 다수결 투표</li>
<li>간접 투표(soft voting) : 예측의 &#39;평균&#39; 이용</li>
</ul>
<p>투표 기반 분류기는 여러 개의 모델을 학습시킨 후 각 분류기의 예측을 집계하는 것이다! (집단 지성을 생각하면 좋을 것 같다)</p>
<p>직접 분류기의 경우 각각의 분류기에게 분류값을 취합한 후, 가장 많이 분류된 것으로 예측을 낸다. 신기하게도 이렇게 하면 각각의 분류기 중 가장 뛰어난 것보다도 정확도가 높은 경우가 많다!</p>
<p>각각은 약할지라도 모이면 더 큰 성과를 낸다는 것이 포인트다!
<strong>약한 학습기(weak learner) → 강한 학습기(strong learner)</strong></p>
<blockquote>
<p>이런 효과가 가능한 이유 : <strong>큰 수의 법칙(law of large numbers)</strong></p>
</blockquote>
<p>앙상블 기법은 기본적으로 여러 모델이 예측하게 되기에 여러 번 예측하는 것과 다름 없다. 그래서</p>
<ul>
<li>서로 독립적일 때</li>
<li>각각의 오차에 상관관계가 없을 때</li>
</ul>
<p>이런 경우 앙상블의 정확도가 올라가게 된다.
(각기 다른 알고리즘으로 학습시키는 것이 곧 매우 다른 종류의 오차를 만들 수 있다 .)</p>
<h3 id="sklearn의-votingclassifier"><code>sklearn</code>의 <code>VotingClassifier</code></h3>
<p>이름/예측기 쌍의 리스트만 제공하면 일반 분류기처럼 쉽게 사용 가능하다.
투표 기반 분류기의 <code>predict()</code> 메서드를 호출하면 직접 투표를 진행한다.</p>
<h1 id="72-배깅과-페이스팅">7.2 배깅과 페이스팅</h1>
<p>다양한 분류기를 만드려면...</p>
<ul>
<li>각기 다른 알고리즘 활용(투표 기반 분류기에서 다룬 내용!)</li>
<li><strong>같은 알고리즘 + 훈련 세트의 subset 랜덤 구성</strong></li>
</ul>
<p>이때 훈련 세트에서 샘플링 하는 방식에 따라 <strong>배깅</strong>과 <strong>페이스팅</strong>이 나뉜다. </p>
<p>✅<strong>배깅 : 중복을 허용하여 샘플링</strong>
(bootstrap aggregating의 줄임말) → (bagging)</p>
<p>✅<strong>페이스팅 : 중복을 허용하지 않고 샘플링</strong>
pasting</p>
<p>_통계학에서는 중복을 허용한 resampling을 bootstrapping이라고 한다고 한다 _</p>
<p>✅집계 함수</p>
<ul>
<li>분류 : 통계적 최빈값(statiscal mode, 직접 투표 분류기처럼 가장 많은 예측 결과)</li>
<li>회귀 : 평균 계산</li>
</ul>
<p>개별 예측기는 편향 큼
집계 함수 통과하면 편향 분산 모두 감소
일반적으로 앙상블 결과 : 편향 비슷, 분산 감소</p>
<p>⭐ 장점 : 예측기는 무려 <strong>병렬</strong>로 학습 가능!
→ 유사하게 <strong>예측</strong>도 <strong>병렬</strong>로 가능!
→ 그냥 cpu만 때려박으면 되잖아!!!
→ 그래서 인기가 많다고 한다!</p>
<h3 id="sklearn의-bagging--pasting"><code>sklearn</code>의 Bagging &amp; Pasting</h3>
<ul>
<li><code>BaggingClassifier</code><ul>
<li>기반이 되는 분류기가 클래스 확률 추정이 가능하면 (=<code>predict_proba()</code>함수 있으면) 직접 투표 대신 <strong>간접 투표 방식 사용</strong></li>
</ul>
</li>
<li><code>BaggingRegressor</code><ul>
<li>회귀용</li>
</ul>
</li>
</ul>
<h3 id="oob-평가">OOB 평가</h3>
<p>배깅을 이용하면 어떤 샘플은 전혀 선택되지않을 수 있음
→ 이걸 이용하여 각 예측기를 평가하여 OOB 평가의 평균을 앙상블의 평가로 활용할 수 있음!</p>
<h1 id="73-랜덤-패치와-서브스페이스">7.3 랜덤 패치와 서브스페이스</h1>
<p><code>BaggingClassifier</code> </p>
<p>✅ 랜덤 패치 방식(random patches method)
훈련 특성과 샘플을 모두 샘플링하는 것</p>
<p>✅ 랜덤 서브스페이스 방식(random subspaces method)
훈련 샘플을 모두 사용하고 특성을 샘플링하는 것</p>
<h1 id="74-그저-갓치트키-랜덤-포레스트">7.4 그저 갓...치트키 랜덤 포레스트</h1>
<p>한마디로 정리! 랜덤 포레스트는 Bagging 또는 Pasting을 적용한 Ensemble이다!</p>
<p><code>BaggingClassifier</code>에 <code>DecisionTreeClassifier</code> 대신 결정 트리에 최적화되어 사용하기 편한 <code>RandomForestRegressor</code>를 사용하면 된다!</p>
<p>랜덤 포레스트 알고리즘)</p>
<ul>
<li>랜덤으로 선택한 후보 중에서 최적의 특성을 찾음(무작위성 주입)</li>
<li>기본적으로 전체 특성 개수가 $n$이면 $\sqrt n$개의 특성을 선택</li>
<li>트리 다양한게 만든다 
→ 편향 손해, but 분산 ↓ :전체적으로 더 훌륭한 모델</li>
</ul>
<h3 id="sklearn의-randomforestclassifier"><code>sklearn</code>의 <code>RandomForestClassifier</code></h3>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html">sklearn RandomForestClassifier</a></p>
<pre><code class="language-python">class sklearn.ensemble.RandomForestClassifier(n_estimators=100, *, criterion=&#39;gini&#39;, 
max_depth=None, min_samples_split=2, min_samples_leaf=1, 
min_weight_fraction_leaf=0.0, max_features=&#39;sqrt&#39;, max_leaf_nodes=None, 
min_impurity_decrease=0.0, bootstrap=True, oob_score=False, n_jobs=None, 
random_state=None, verbose=0, warm_start=False, class_weight=None, ccp_alpha=0.0, 
max_samples=None, monotonic_cst=None)</code></pre>
<p><code>splitter</code> : <code>DecisionTreeRegressor</code>에 있던 항목이다.</p>
<ul>
<li><p><code>best</code> (기본값)이면 노드를 적절하게 나누고 (임곗값 활용) </p>
</li>
<li><p><code>random</code>이면 노드를 랜덤하게 나눈다 → 후보 특성을 사용해 랜덤 분할 후 그 중 최상의 분할 선택</p>
<h3 id="741-엑스트라-트리">7.4.1 엑스트라 트리</h3>
<p>이렇게 극단적으로 랜덤한 트리의 랜덤 포레스트는 <strong>익스트림 랜덤 트리(extremely randomized tree) 앙상블 또는 줄여서 엑스트라 트리(extra-tree)라고 함.)</strong></p>
</li>
<li><p>랜덤 포레스트이기에 편향이 늘어나는 대신 분산은 낮아짐</p>
</li>
<li><p>모든 노드에서 특성마다 가장 최적의 임계값 찾는 것은 트리 알고리즘에서 가장 많은 시간을 소요함.</p>
<ul>
<li>그래서 랜덤 포레스트보다 엑스트라 트리의 훈련 속도가 훬씬 더 빠름.</li>
</ul>
<p><code>sklearn</code>에서 <code>ExtraTreesClassifier</code> 사용</p>
<ul>
<li><p>참고로 이 함수에서 <code>boostrap = &quot;False&quot; {default}</code>를 제외하곤 <code>RandomForestClassifier</code>와 같음.</p>
</li>
<li><p>참고로 <code>ExtraTreeRegressor</code>에서도 <code>boostrap = &quot;False&quot; {default}</code>를 제외하곤 <code>RandomForestRegressor</code>와 같은 API 제공</p>
</li>
<li><p>엑스트리와 일반 랜덤 포레스트 중 어떤 것이 나은지 보려면 교차 검증으로 비교하는 것이 유일함.</p>
</li>
</ul>
</li>
</ul>
<h3 id="sklearn의-randomforestregressor"><code>sklearn</code>의 <code>RandomForestRegressor</code></h3>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html">sklearn RandomForestRegressor</a></p>
<pre><code class="language-python">class sklearn.ensemble.RandomForestRegressor(n_estimators=100, *, 
criterion=&#39;squared_error&#39;, max_depth=None, min_samples_split=2, 
min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=1.0, 
max_leaf_nodes=None, min_impurity_decrease=0.0, bootstrap=True, 
oob_score=False, n_jobs=None, random_state=None, verbose=0, 
warm_start=False, ccp_alpha=0.0, max_samples=None, monotonic_cst=None)</code></pre>
<p><code>RandomForestRegressor</code>에는 <code>split</code> 항목 없음</p>
<h3 id="742-특성-중요도">7.4.2 특성 중요도</h3>
<blockquote>
<p>랜덤 포레스트 장점 → 특성의 상대적 중요도를 쉽게 측정</p>
</blockquote>
<ul>
<li>sklearn에서 어떤 특성을 사용한 노드가 평균적으로 불순도를 얼마나 감소시키었는지 확인하여 특성의 중요도를 측정할 수 있다. (정확히는 가중치 평균을 보는 것이며, 각 노드의 가중치는 연관된 훈련 샘플 수와 같음)</li>
</ul>
<blockquote>
<p>property feature_importances_
The impurity-based feature importances.</p>
</blockquote>
<ul>
<li>특성의 중요도가 높다 = 특성이 모델에서 더 중요하다</li>
<li>특성의 중요도는 해당 특성이 가져오는 기준(criterion, 보통 불순도)의 총 감소량으로 계산</li>
<li>랜덤 포레스트는 특성 선택 시 어떤 특성이 중요한지 빠르게 확인 가능해서 매우 편리함.</li>
</ul>
<h1 id="75-부스팅-boosting">7.5 부스팅 (boosting)</h1>
<blockquote>
<p>부스팅(boosting)
원래 가설 부스팅(hypothesis boosting)이라 불렸음.</p>
</blockquote>
<p>약한 학습기를 연결하여 강한 학습기를 만드는 앙상블 방법으로,
앞의 모델을 <strong>보완</strong>하면서 일련의 예측기를 학습한다.</p>
<h3 id="adaboost-adaptive-boosting-에이다-부스트">AdaBoost (adaptive boosting, &#39;에이다 부스트&#39;)</h3>
<p>인기있는 부스팅 방법 중 하나이다.</p>
<p>이전 예측기를 보완할 때, 이전 모델이 과소적합했던 훈련 샘플의 가중치를 더 높여서 새로운 예측기를 만듦.</p>
<ul>
<li>이 과정을 따라가면서 새로운 예측기는 학습하기 어려운 샘플에 점점 맞춰짐.</li>
<li>다음 업데이트 시, 다음 알고리즘이 잘못 분류된 훈련 샘플의 가중치를 상대적으로 높임 → 다음 분류기는 업데이트된 가중치를 사용해 훈련 세트에서 훈련 및 예측, 가중치 업데이트</li>
</ul>
<p>훈련 마치면 배깅이나 페이스팅과 비슷한 방식으로 예측을 만듦
가중치가 적용된 훈련 세트의 전반적인 정확도에 따라 예측기마다 다른 가중치 적용</p>
<blockquote>
<p>중요한 단점</p>
</blockquote>
<p>각 예측기는 이전 예측기가 훈련되고 평가된 후에 학습될 수 있기에 훈련 병렬화 불가
→ 배깅이나 페이스팅만큼 확장성 높지 X</p>
<h3 id="그레이디언트-부스팅-gradient-boosting">그레이디언트 부스팅 gradient boosting</h3>
<p>또 다른 인기 부스팅 알고리즘</p>
<p>AdaBoost처럼 그레이디언트 부스팅은 앙상블에 이전까지의 오차를 보정하도록 예측기를 순차적으로 추가차를 보정하도록 예측기를 순차적으로 추가, AdaBoost와 다르게 <strong>이전 예측기가 만든 잔여 오차(residual error)</strong>에 새로운 예측기 학습</p>
<ul>
<li>GRBT<ul>
<li><code>gradient tree boosting</code>, <code>gradient boosted regression</code></li>
<li>결정트리에 기반한 예측기를 사용하는 방식이다.</li>
<li>축소(shrinkage)<ul>
<li><code>learning rate</code>가 각 트리의 기여도 조절 → 낮게 설정하면 앙상블을 훈련 세트에 학습시키기 위해 많은 트리가 필요하지만 일반적으로 예측의 성능은 좋아짐</li>
<li><strong>확률적 그레이디언트 부스팅(stohastic gradient boosting)</strong> : 무작위성을 추가한 것 (무작위 데이터 샘플링을 통해 이루어짐)</li>
<li>유명한 XGBoost, LightGBM, CatBoost 가 이에 해당</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="히스토그램-기반-그레디언트-부스팅hgb">히스토그램 기반 그레디언트 부스팅(HGB)</h3>
<ul>
<li>HGB는 대규모 데이터셋에서 일반 GBRT보다 수백 배 빠르게 훈련 가능</li>
<li>구간 분할은 규제처럼 작동 → 정밀도 손실 유발 → 
과대적합 줄이는 데 도움될 수도 있으나 과소적합 유발할 수도 있음.</li>
</ul>
<h1 id="76-스태킹-staking">7.6 스태킹 (staking)</h1>
<p>스태킹은 stacked generalization의 줄임말이다.</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/0f405eb4-4c5e-4b46-9bd8-a3aaf3ec9189/image.png" width = 80% disply =block margin = 4> </p>


<p>그동안 모든 예측기의 예측을 취합하는 간단한 함수를 사용해왔다. 하지만 스태킹은 이 간단한 함수를 갈아치우고, 이렇게 취합하는 것 자체를 학습시킨다! (정말 별걸 다 훈련시키려고 하네)</p>
<p>n개의 예측기가 각각의 예측을 내놓으면, 마지막 예측기(블렌더, blender 또는 메타 학습기 meta learner)가 각 예측들을 입력으로 받아 최종 예측을 만드는 것이다.</p>
<h3 id="어떻게-갈아버리만들지">어떻게 <del>갈아버리</del>만들지?!</h3>
<p><strong>1. 먼저 데이터 준비부터! 데이터 분할 (Training and Validation Split)</strong></p>
<ul>
<li>훈련 데이터를 기본 모델들이 학습하고 예측하도록 분할</li>
<li>일반적으로 교차 검증(cross-validation) 방식을 사용하여 다양한 데이터 분할에서 모델 성능을 평가</li>
</ul>
<p><strong>2. 기본 모델 (Base Models) 훈련</strong></p>
<ul>
<li>다양한 알고리즘을 선택하여 각각의 기본 모델을 학습</li>
<li>각 기본 모델이 예측한 값을 저장
→ 이 예측값들은 나중에 메타 모델의 입력으로 사용</li>
</ul>
<p><strong>3. 예측 결과 저장 (Save Predictions)</strong></p>
<ul>
<li>기본 모델들이 만든 예측 결과를 훈련 데이터로부터 별도로 저장</li>
<li>일반적으로... <ul>
<li>훈련 데이터의 일부 → 모델을 학습</li>
<li>나머지 데이터 → 예측에 활용(예측값 get)</li>
</ul>
</li>
</ul>
<p><strong>4. 메타 모델 (Meta Model) 훈련</strong></p>
<ul>
<li>메타 데이터셋 생성<ul>
<li>기본 모델들의 예측값을 특징(feature)으로 사용</li>
</ul>
</li>
<li>메타 모델 학습<ul>
<li>주로 간단한 회귀 모델 이용 (선형 회귀, 로지스틱 회귀)</li>
<li>복잡한 메타 모델을 사용할 수도 있음!(XGBoost 등)<ul>
<li>기본 모델 간의 예측이 비선형적인 관계 가질 때</li>
<li>대규모 데이터셋</li>
<li>기본 모델 간의 상호작용 효과 고려해야할 때</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>5. 최종 예측 (Final Prediction)</strong></p>
<ul>
<li>테스트 데이터가 주어짐<ul>
<li>기본 모델들 : 각각 예측을 수행 → 메타 모델에 입력할 예측값을 생성</li>
<li>메타 모델 : 이 예측값을 조합하여 최종 예측 결과를 출력</li>
</ul>
</li>
</ul>
<blockquote>
<p>왜 간단한 모델을 메타 모델로 쓸까?</p>
</blockquote>
<p>크게 세 가지 이유가 있다.
<strong>1. 과적합 방지</strong>
이미 기본 모델에서 다양한 패턴을 학습하기에 메타 모델까지 복잡해지면 과적합될 가능성이 큼.
<strong>2. 해석 용이성</strong>
선형 회귀나 로지스틱 회귀 모델은 해석이 간단하여 각 기본 모델이 메타 모델에 얼마나 기여하는지를 쉽게 알 수 있음.
<strong>3. 계산 비용 절감</strong>
간단한 모델은 훈련 속도가 빠르고, 파라미터 튜닝이 덜 필요함 → 특히 스태킹 과정에서는 이미 여러 기본 모델을 학습하기 때문에 메타 모델은 가볍고 빠르게 설정하는 것이 효율적</p>
<h3 id="sklearn의-stackingclassifier"><code>sklearn</code>의 <code>StackingClassifier</code></h3>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.StackingClassifier.html">sklearn StackingClassifier</a></p>
<pre><code class="language-python">class sklearn.ensemble.StackingClassifier(estimators, 
final_estimator=None, *, cv=None, stack_method=&#39;auto&#39;, 
n_jobs=None, passthrough=False, verbose=0)[source]</code></pre>
<p><code>estimators</code> : list of(str, estimator)</p>
<ul>
<li>베이스 모델을 여기에 넣는다. </li>
<li>각 베이스 추정기는 리스트의 요소로 정의되며, 각 요소는 튜플 형태다.(문자열_추정기 이름, 추정기 인스턴스_실제 모델 객체로 이루어진다.) </li>
<li>&#39;set_params&#39; 메서드를 사용하여 특성 추정기를 drop가능, </li>
<li>일반적으로 베이스 추정기는 분류기(classifier)가 되며, 특성 사용 사례(순서형 회귀 등)에서는 베이스 추정기로도 활용 가능하다. </li>
</ul>
<p>최종 예측기 기본값 : <code>LogisticRegression</code> 사용
<code>stack_method</code> : {‘auto’, ‘predict_proba’, ‘decision_function’, ‘predict’}, default=’auto’</p>
<ul>
<li>사용 가능한 경우엔 <code>predict_proba()</code> 호출</li>
<li>그 다음 순위 : <code>decision_function</code> 호출</li>
<li>최후의 수단 : <code>predict()</code> 호출</li>
</ul>
<h3 id="sklearn의-stackingregressor"><code>sklearn</code>의 <code>StackingRegressor</code></h3>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.StackingRegressor.html">sklearn StackingRegressor</a></p>
<pre><code class="language-python">class sklearn.ensemble.StackingRegressor(estimators, 
final_estimator=None, *, cv=None, n_jobs=None, passthrough=False, 
verbose=0)</code></pre>
<p><code>StackingClassifier</code>와 비슷한데, `stack_method=&#39;auto&#39;는 없다.</p>
<p>최종 예측기 기본값 : <code>RidgeCV</code> 사용 (<a href="https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.RidgeCV.html#sklearn.linear_model.RidgeCV">RidgeCV</a>)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[optimization] Dual Problem]]></title>
            <link>https://velog.io/@yoonie_03/optimization-Dual-Problem</link>
            <guid>https://velog.io/@yoonie_03/optimization-Dual-Problem</guid>
            <pubDate>Mon, 04 Nov 2024 18:49:10 GMT</pubDate>
            <description><![CDATA[<p>원 문제(primal problem) : 제약 있는 최적화 문제 
→ 쌍대 문제(dual problem)라고 하는 깊게 관련된 다른 문제로 표현 가능</p>
<p>*일반적으로 쌍대 문제의 해는 원 문제 해의 하한값
But!! 어떤 조건 하에서는 원 문제와 똑같은 해 제공함.
→ SVM에서 이 조건 만족
→ 원 문제 또는 쌍대 문제 중 선택(골라골라~)</p>
<h3 id="선형-svm-목적-함수의-쌍대-형식">선형 SVM 목적 함수의 쌍대 형식</h3>
<ul>
<li><p>QP 솔버로 식을 최소화하는 벡터 $\hat{\alpha}$을 찾았다면 원 문제 식 최소화하는 $\hat{\mathbf{w}}$과 $\hat{b}$을 계산 가능</p>
</li>
<li><p>쌍대 문제에서 구한 해로 원 문제의 해 계산
$$
\hat{\mathbf{w}} = \sum_{i=1}^{m} \hat{\alpha}^{(i)} t^{(i)} \mathbf{x}^{(i)}
$$</p>
</li>
</ul>
<p>$$
\hat{b} = \frac{1}{n_s} \sum_{i=1}^{m} \left( t^{(i)} - \hat{\mathbf{w}}^T \mathbf{x}^{(i)} \right)_{\hat{\alpha}^{(i)} &gt; 0}
$$</p>
<h3 id="커널-svm">커널 SVM</h3>
<ul>
<li>2차 다항식 매핑 함수</li>
<li><em>Equation 5-8. Second-degree polynomial mapping*</em></li>
</ul>
<p>$$
\phi(\mathbf{x}) = \phi\left( \begin{pmatrix} x_1 \ x_2 \end{pmatrix} \right) = \begin{pmatrix} x_1^2 \ \sqrt{2} x_1 x_2 \ x_2^2 \end{pmatrix}
$$</p>
<ul>
<li>2차 다항식 매핑을 위한 커널 트릭</li>
</ul>
<p><strong>Equation 5-9. Kernel trick for a 2^{nd}-degree polynomial mapping</strong></p>
<p>$$
\phi(\mathbf{a})^T \phi(\mathbf{b}) = 
\begin{pmatrix}
a_1^2 \
\sqrt{2} a_1 a_2 \
a_2^2 
\end{pmatrix}^T
\begin{pmatrix}
b_1^2 \
\sqrt{2} b_1 b_2 \
b_2^2 
\end{pmatrix} 
= a_1^2 b_1^2 + 2 a_1 b_1 a_2 b_2 + a_2^2 b_2^2
$$</p>
<p>$$
= (a_1 b_1 + a_2 b_2)^2 = 
\begin{pmatrix}
a_1 \
a_2 
\end{pmatrix}^T
\begin{pmatrix}
b_1 \
b_2 
\end{pmatrix}^2 
= (\mathbf{a}^T \mathbf{b})^2
$$</p>
<p>결론 : $\phi$가 2차 다항식 변환이라면 백터 접곱을 간단하게 바꿀 수 있음
→ 실제로 후련 샘플 변환할 필요 X</p>
<p>장점 : 계산 측에서 효율적</p>
<p>2차 다항식 커널 : $K(\mathbf{a}, \mathbf{b}) = (\mathbf{a}^T \mathbf{b})^2$</p>
<h2 id="커널">커널</h2>
<p>머신러닝에서 커널은 변환 $\phi$를 계산하지 않고도 또는 아예 모르더라도
원래 벡터에 기반하여 점곱을 계산할 수 있는 함수다.</p>
<blockquote>
<p>일반적인 커널들
<strong>Equation 5-10. Common kernels</strong></p>
</blockquote>
<ul>
<li><p><strong>Linear</strong>: 선형
$$
K(\mathbf{a}, \mathbf{b}) = \mathbf{a}^T \mathbf{b}
$$</p>
</li>
<li><p><strong>Polynomial</strong>: 다항식
$$
K(\mathbf{a}, \mathbf{b}) = \left( \gamma \mathbf{a}^T \mathbf{b} + r \right)^d
$$</p>
</li>
<li><p><strong>Gaussian RBF</strong>: 가우스 RBF
$$
K(\mathbf{a}, \mathbf{b}) = \exp \left( -\gamma | \mathbf{a} - \mathbf{b} |^2 \right)
$$</p>
</li>
<li><p><strong>Sigmoid</strong>: 시그모이드
$$
K(\mathbf{a}, \mathbf{b}) = \tanh \left( \gamma \mathbf{a}^T \mathbf{b} + r \right)
$$</p>
</li>
</ul>
<blockquote>
<p>커널 SVM으로 예측
<strong>Equation 5-11. Making predictions with a kernelized SVM</strong></p>
</blockquote>
<p>$$
h_{\hat{\mathbf{w}}, \hat{b}} \left( \phi(\mathbf{x}^{(n)}) \right) = \hat{\mathbf{w}}^T \phi(\mathbf{x}^{(n)}) + \hat{b} = \left( \sum_{i=1}^{m} \hat{\alpha}^{(i)} t^{(i)} \phi(\mathbf{x}^{(i)}) \right)^T \phi(\mathbf{x}^{(n)}) + \hat{b}
$$</p>
<p>$$
= \sum_{i=1}^{m} \hat{\alpha}^{(i)} t^{(i)} \left( \phi(\mathbf{x}^{(i)})^T \phi(\mathbf{x}^{(n)}) \right) + \hat{b}
$$</p>
<p>$$
= \sum_{i=1}^{m} \hat{\alpha}^{(i)} t^{(i)} K(\mathbf{x}^{(i)}, \mathbf{x}^{(n)}) + \hat{b} \quad \text{for } \hat{\alpha}^{(i)} &gt; 0
$$</p>
<blockquote>
<p>커널 트릭으로 사용한 편향 계산
<strong>Equation 5-12. Computing the bias term using the kernel trick</strong></p>
</blockquote>
<p>$$
\hat{b} = \frac{1}{n_s} \sum_{i=1}^{m} \left( t^{(i)} - \hat{\mathbf{w}}^T \phi(\mathbf{x}^{(i)}) \right)<em>{\hat{\alpha}^{(i)} &gt; 0} 
= \frac{1}{n_s} \sum</em>{i=1}^{m} \left( t^{(i)} - \left( \sum_{j=1}^{m} \hat{\alpha}^{(j)} t^{(j)} \phi(\mathbf{x}^{(j)}) \right)^T \phi(\mathbf{x}^{(i)}) \right)_{\hat{\alpha}^{(i)} &gt; 0} 
$$</p>
<p>$$
= \frac{1}{n_s} \sum_{i=1}^{m} \left( t^{(i)} - \sum_{j=1}^{m} \hat{\alpha}^{(j)} t^{(j)} K(\mathbf{x}^{(i)}, \mathbf{x}^{(j)}) \right)_{\hat{\alpha}^{(i)} &gt; 0}
$$</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] SVM 이론]]></title>
            <link>https://velog.io/@yoonie_03/ML-SVM-%EC%9D%B4%EB%A1%A0</link>
            <guid>https://velog.io/@yoonie_03/ML-SVM-%EC%9D%B4%EB%A1%A0</guid>
            <pubDate>Mon, 04 Nov 2024 18:32:29 GMT</pubDate>
            <description><![CDATA[<h2 id="1-예측">1) 예측</h2>
<p>선형 SVM 모델 → 단순히 결정 함수를 계산해서 새로운 샘플 x의 클래스 예측
결정 함수  : $\boldsymbol{\theta}^T \textbf{x} = \theta_0 +\theta_1 x_1 + \cdots + \theta_n x_n$</p>
<p> | 결과 &gt; 0 → 양성(1)
| 결과 ≤ 0 → 음성(0)</p>
<p>➡️  선형 SVM 분류기로 예측하는 것은<code>LogisticRegression</code>과 같음! </p>
<h2 id="2-훈련">2) 훈련</h2>
<p>충족해야 하는 조건
✅ 마진 오류 횟수 제한
✅ 마진 커지게 하는 가중지 벡터 $\textbf w$와 편향 $b$ 찾기</p>
<p>$\textbf s=\textbf w \textbf x+b$</p>
<p>$\textbf w$ ↑ : 마진 ↓
 $b$ : 마진 크기에 영향 X</p>
<blockquote>
<p> 도로 넓히려면 $\textbf w$ 가능한 한 작게 유지해야함</p>
</blockquote>
<h3 id="하드-마진-선형-svm-분류기의-목적-함수">하드 마진 선형 SVM 분류기의 목적 함수</h3>
<p> <strong>Hard margin linear SVM classifier objective</strong></p>
<p>$$
\text{minimize}_{\mathbf{w}, b} \quad \frac{1}{2} \mathbf{w}^T \mathbf{w} \
$$
$$
\text{subject to} \quad t^{(i)} \left( \mathbf{w}^T \mathbf{x}^{(i)} + b \right) \geq 1, \quad \text{for } i = 1, 2, \dots, m
$$</p>
<blockquote>
<p>소프트 마진 분류기 목적 함수 구성하려면 각 샘플에 대해 
<strong>샘플 변수 (slack variable)</strong> $\zeta^{(i)} \geq 0$ 도입 필요</p>
</blockquote>
<p>$\zeta^{(i)}$ : $i$번째 샘플이 얼마나 마진을 위반할 지 결정</p>
<p>목표 1 : 마진 오류 최소화를 위해 슬랙 변수 최소화
목표 2 : 마진 최대화를 위해 $\frac{1}{2} \mathbf{w}^T \mathbf{w}$ 최소화</p>
<p>→ <strong>목표 1과 2 상충</strong> :  마진을 최대화하려면 마진을 넓게 가져가야 하지만, 슬랙 변수를 최소화하려면 모든 포인트가 마진 바깥에 놓여야 함.</p>
<p>→하이퍼파라미터 <code>C</code>로 이 두 목표의 트레이드 오프 정의</p>
<p>✅ C가 크다</p>
<ul>
<li>슬랙 변수에 대한 패널티가 크다</li>
<li>모델이 슬랙 변수를 최소화하려고 한다
→ 이는 <strong>마진을 좁히면서 오차를 줄이는 방향</strong>으로 작용</li>
</ul>
<p>✅ C가 작다 </p>
<ul>
<li>마진을 최대화하는 것이 더 중요한 목표가 됨.</li>
<li>일부 데이터 포인트가 마진을 침범하더라도 <strong>넓은 마진을 유지하고자 함</strong></li>
</ul>
<h3 id="소프트-마진-선형-svm-분류기의-목적-함수">소프트 마진 선형 SVM 분류기의 목적 함수</h3>
<p> <strong>Soft margin linear SVM classifier objective</strong></p>
<p>$$
\text{minimize}<em>{\mathbf{w}, b, \zeta} \quad \frac{1}{2} \mathbf{w}^T \mathbf{w} + C \sum</em>{i=1}^{m} \zeta^{(i)}
$$
$$
\text{subject to} \quad t^{(i)} \left( \mathbf{w}^T \mathbf{x}^{(i)} + b \right) \geq 1 - \zeta^{(i)}, \quad \zeta^{(i)} \geq 0, \quad \text{for } i = 1, 2, \dots, m
$$</p>
<h2 id="3-qp-문제">3) QP 문제</h2>
<blockquote>
<p>하드 마진 과 소프트 마진 문제는 모두 선형적인 제약 있는 볼록 함수의 이차 최적화 문제 → Quadratic programming 문제라고 함!</p>
</blockquote>
<p>SVM 훈련 방법</p>
<ul>
<li>QP solver 사용</li>
<li>경사하강법 → hinge loss와 squared hinge loss 최소화</li>
</ul>
<p>&lt;과정&gt;</p>
<ul>
<li><p>양성 클래스 샘플 $\mathbf{x}$ (t=1)가 주어질 때...</p>
<ul>
<li>결정 함수 s &gt; 1 → 손실 0 (도로에서 벗어나 샘플이 <strong>양성 클래스</strong>에 위치) </li>
</ul>
</li>
<li><p>음성 클래스 샘플 $\mathbf{x}$ (t=-1)가 주어질 때...</p>
<ul>
<li>결정 함수 s ≤ -1 → 손실 0 (도로에서 벗어나 샘플이 <strong>음성 클래스</strong>에 위치)</li>
</ul>
</li>
<li><p>샘플이 마진에서 멀어질수록 손실이 커짐</p>
<ul>
<li>힌지 손실 : 선형적으로</li>
<li>제곱 힌지 손실 : 이차 방정식으로<ul>
<li>이상치에 더 민감하게 반응</li>
<li>이상치가 없으면 더 빨리 수렴</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><code>LinearSVC</code>  : 제곱 힌지 사용
<code>SGDClassifier</code> : 힌지 손실 사용</p>
<h2 id="sgdclassifier"><code>SGDClassifier</code></h2>
<ul>
<li>보통 힌지 손실 사용하지만 옵션에는 
hinge loss와 squared hinge loss 두 개 다 있음!</li>
<li><code>Loss</code> 항목 : </li>
</ul>
<pre><code class="language-python">loss{‘hinge’, ‘log_loss’, ‘modified_huber’, ‘squared_hinge’, 
‘perceptron’, ‘squared_error’, ‘huber’, ‘epsilon_insensitive’, 
‘squared_epsilon_insensitive’}, default=’hinge’</code></pre>
<p>SVC 클래스의 최적화 알고리즘은 힌지 손실을 최소화하는 것과 유사한 솔루션 찾음.</p>
<p>참고한 문서 : <a href="https://scikit-learn.org/dev/modules/generated/sklearn.linear_model.SGDClassifier.html">[사이킷런 SGDClassifier]</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]6장 결정 트리]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning6%EC%9E%A5-%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%AC</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning6%EC%9E%A5-%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%AC</guid>
            <pubDate>Mon, 28 Oct 2024 13:49:06 GMT</pubDate>
            <description><![CDATA[<p>알고리즘에서도 느끼는 거지만 Tree 구조가 정말 중요한 것 같다. 앞으로 랜덤 포레스트의 기본 구성 요소가 결정 트리라고 하니 잘 정리해 보려고 한다!</p>
<p>결정 트리는 분류와 회귀 작업, 다중 출력 작업까지 가능한 ML 알고리즘이다. </p>
<h1 id="🔥6162-결정-트리-학습과-시각화-예측">🔥6.1~6.2 결정 트리 학습과 시각화, 예측</h1>
<p>이해를 위해 모델을 하나 만들어서 예측하는 방법에 대해 알아보았다.</p>
<pre><code class="language-python"># Train DecisionTreeClassifier on the iris dataset
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier

iris = load_iris(as_frame=True)
X_iris = iris.data[[&quot;petal length (cm)&quot;, &quot;petal width (cm)&quot;]].values
y_iris = iris.target

tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf .fit(X_iris, y_iris)</code></pre>
<p>아래와 같이 결과가 나왔다.
<code>DecisionTreeClassifier(max_depth=2, random_state=42)</code></p>
<pre><code class="language-python">from sklearn.tree import export_graphviz

export_graphviz(tree_clf, 
                out_file=&quot;iris_tree.dot&quot;, 
                feature_names=[&quot;꽃잎 길이(cm)&quot;, &quot;꽃잎 너비 (cm)&quot;],
                class_names=iris.target_names,
               rounded=True,
               filled=True)</code></pre>
<pre><code class="language-python">from graphviz import Source

Source.from_file(&quot;iris_tree.dot&quot;)</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/bd61f8d1-7a9d-4067-845c-716f7901eb85/image.png" width = 80% disply =block margin = 4> </p>


<p>결과로 나온 트리의 구조를 보면, 트리가 어떻게 예측을 하는 지 알 수 있다. </p>
<p>ex) 깊이 2의 왼쪽 노드
value값이 뜻 하는 것
Iris-Setosa : 0% (0/54)
Iris-Versicolor : 90.7%(49/54)
Iris-Virginica : 9.3%(5/54)</p>
<p>만약 클래스를 예측한다면? → 가장 확률(90.7%) 높은 <strong>Iris-Versicolor</strong> 출력</p>
<h2 id="지니-불순도">지니 불순도</h2>
<blockquote>
<p>한 노드의 모든 샘플이 같은 클래스에 속해 있다면 이 노드는 순수(gini=0) 하다고 한다.</p>
</blockquote>
<p>$$
G_i = 1-\sum_{k=1}^n {P_{i,k}}^2
$$</p>
<p>$G_i$는 $i$번째 노드의 지니 불순도
$p_{i,k}$는 $i$번째 노드에 있는 훈련 샘플 중 클래스 $k$에 속한 샘플의 비율</p>
<h2 id="엔트로피">엔트로피</h2>
<blockquote>
<p>모든 메시지가 동일할 때 엔트로피=0
메시지의 평균 정보량을 측정하는 섀넌의 <strong>정보이론</strong>도 이에 해당</p>
</blockquote>
<p><code>DecisionTreeClassifier</code> 클래스는 <strong>지니 불순도</strong> 사용
❗다만❗ <code>criterion=&quot;entropy&quot;</code> 로 지정하여 <strong>엔트로피 불순도</strong> 사용 가능</p>
<p>$$
H_i = -\sum_{k=1,,P_{i,k}\neq0}^n P_{i,k} log_2(P_{i,k})
$$</p>
<blockquote>
<p><strong>지니 불순도 vs 엔트로피</strong></p>
</blockquote>
<p>실제로는 큰 차이가 없다고 한다.
<strong>지니 불순도 특징</strong> : 계산이 더 빠름, 단 빈도 높은 클래스를 한쪽 branch로 고립시키는 경향 있음.
<strong>엔트로피 특징</strong> : 조금 더 균형 잡힌 트리를 만듦
→ <a href="https://goo.gl/TbjeNx">Sebastian Raschka 분석</a></p>
<h1 id="🔥64-cart-훈련-알고리즘">🔥6.4 CART 훈련 알고리즘</h1>
<ul>
<li><p>훈련 세트를 하나의 특성 $k$와 임곗값 $t_k$를 사용해 두 개의 서브셋으로 나눈다.</p>
<ul>
<li>이 때 가중치가 적용된 가장 순수한 서브셋으로 나눌 수 있는 $(k, t_k)$ 쌍을 찾는다</li>
<li>이 쌍을 구하기 위해 최소화해야 하는 비용 함수
$$
J(k, t_k) = \frac{m_{left}}{m}G_{left}+\frac{m_{right}}{m}G_{right}
$$
$G_{left/right}$ : 왼쪽 / 오른쪽 서브셋의 불순도
$m_{left/right}$ : 왼쪽 / 오른쪽 서브셋의 불순도</li>
</ul>
</li>
<li><p>최대 깊이(<code>max_depth</code>)가 되거나 불순도를 줄이는 분할을 찾을 수 없을 때 멈추게 된다.</p>
</li>
</ul>
<h1 id="🔥65-계산-복잡도">🔥6.5 계산 복잡도</h1>
<ul>
<li><p>예측을 위해서는 결정 트리의 루트 노드~리프 노드까지 탐색
→ 트리는 균형을 이루므로 결정 트리를 탐색하기 위해서는 $O(log_2(m))$개의 노드를 거쳐야 한다.</p>
</li>
<li><p>이때 각 노드의 하나의 특성값만 확인 
→ 예측에 필요한 전체 복잡도는 특성과 무관하게 $O(log_2(m))$
→ 데이터가 많아져도 <strong>빠른 시간</strong>안에 가능!</p>
</li>
<li><p>각 노드에서 훈련 샘플의 모든 특성을 비교</p>
<ul>
<li>이때 <code>max_features</code>가 지정되어 있다면 이 값까지만
→ 훈련 복잡도 : $O(n \times mlog_2(m))$</li>
</ul>
</li>
</ul>
<h1 id="🔥67-규제-매개변수">🔥6.7 규제 매개변수</h1>
<blockquote>
<p><strong>비파라미터 모델(nonparameter model)</strong> : 과대적합 ↑ 과소적합 ↓
훈련 데이터 제약 거의 X, 훈련되기 전에 파라미터 수 결정 X 
→ 비파라미터 모델로 분류</p>
</blockquote>
<blockquote>
<p><strong>파라미터 모델(parameter model)</strong> : 과대적합 ↓ 과소적합 ↑
파라미터 수 이미 결정 (자유도 제한)</p>
</blockquote>
<p>결정 트리는 비파라미터 모델이기에 어느 정도 자유도를 제한할 필요가 있다. 이를 위해 <strong>규제 매개변수</strong>가 존재한다. 사이킷런에서는 기본값은 제한이 없다.</p>
<h1 id="🔥decisiontreeclassifier🔥">🔥<code>DecisionTreeClassifier</code>🔥</h1>
<blockquote>
<p>규제를 증가시키는 법 
<code>min_</code> : 매개변수 증가 <code>max_</code>: 매개변수 감소</p>
</blockquote>
<pre><code class="language-python">class sklearn.tree.DecisionTreeClassifier(*, 
criterion=&#39;gini&#39;, splitter=&#39;best&#39;, max_depth=None,
min_samples_split=2, min_samples_leaf=1, 
min_weight_fraction_leaf=0.0, max_features=None, 
random_state=None, max_leaf_nodes=None, 
min_impurity_decrease=0.0, class_weight=None, ccp_alpha=0.0, 
monotonic_cst=None)[source]</code></pre>
<p>위는 함수의 기본값이다. 자료는 <a href="https://scikit-learn.org/dev/modules/generated/sklearn.tree.DecisionTreeClassifier.html">사이킷런 공식 문서</a> 참고</p>
<p>중요한 매개변수를 몇 개 살펴보자(여기 코드에 적힌 숫자는 모두 기본값이다)
<code>criterion=&#39;gini&#39;</code> : {“gini”, “entropy”, “log_loss”}
: 분할의 품질을 측정, 즉 어떤 기준으로 데이터를 나누었을 때 <strong>그 분할이 얼마나 좋은지를 평가</strong></p>
<p><code>min_samples_split=2</code>:
: 분할되기  위해 노드가 가져 하는 최소 샘플 수</p>
<p><code>max_depth=None</code> : {int}</p>
<ul>
<li><strong>None</strong> : 분할의 깊이 제한이 없음<ul>
<li>각 리프 노드가 순수</li>
<li>남은 샘플 수가 <code>min_samples_split</code>보다 적어 더 이상 나눌 수 없을 때까지 트리를 확장</li>
<li>트리 성장을 제한하지 않기에 과대적합 가능성 ↑</li>
</ul>
</li>
<li><strong>int</strong> : 해당 숫자까지 깊이 제한</li>
</ul>
<p><code>min_samples_leaf=1</code>:<strong>{int or float}</strong>
:리프 노드가 생성되기 위해 가지고 있어야 할 최소 샘플 수</p>
<p><strong>정수값</strong>이면 <strong>해당 값을 최솟값</strong>으로, </p>
<blockquote>
<p>If float, then <code>min_samples_split</code> is a fraction and <code>ceil(min_samples_split * n_samples)</code> are the minimum number of samples for each split.</p>
</blockquote>
<p><strong>실수값</strong>이면** 전체 샘플 수(n_samples)에 대한 비율**로 해석한다.
<code>ceil(min_samples_split * n_samples)</code> 값이 해당 분할을 진행하기 위해 필요한 최소 샘플 수가 되며, 여기서 <code>ceil</code> 함수는 올림 함수다.</p>
<p><code>min_weight_fraction_leaf=0.0</code>
: <code>min_samples_leaf=1</code>와 같지만 <strong>가중치가 부여된 전체 샘플 수에서의 비율</strong></p>
<h2 id="직접-규제-해보기">직접 규제 해보기</h2>
<pre><code class="language-python">from sklearn.datasets import make_moons

X_moons, y_moons = make_moons(n_samples=150,noise=0.2,random_state=42)

tree_clf1 = DecisionTreeClassifier(random_state=42)
tree_clf2 = DecisionTreeClassifier(min_samples_leaf=5, random_state=42)
tree_clf1.fit(X_moons, y_moons) # 규제 X
tree_clf2.fit(X_moons, y_moons) # 규제 O</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/e8d3b1ed-6657-4206-bdc4-a8ebc648470e/image.png" width = 80% disply =block margin = 4> </p>

<p>규제를 가하지 않은 <code>tree_clf1</code>의 정확도(0.898)가 규제를 가한 모델 <code>tree_clf2</code> 보다 정확도(0.92)가 낮게 측정되는 것을 볼 수 있다.</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/af498124-e0aa-420d-a17d-b3fac9b0853b/image.png" width = 80% disply =block margin = 4> </p>



<p>결정 경계를 실제로 그려보면 규제를 가한 모델이 더 일반화가 잘 되는 것을 볼 수 있다.</p>
<h1 id="🔥68-회귀">🔥6.8 회귀</h1>
<p>sklearn의 <code>DecisionTreeRegressor</code>를 사용해서 2차 함수 형태의 데이터셋에서 <code>max_depth=2</code> 설정으로 회귀 트리를 만들어 보았다.</p>
<pre><code class="language-python">import numpy as np
from sklearn.tree import DecisionTreeRegressor

np.random.seed(42)
X_quad = np.random.rand(200, 1)
y_quad = X_quad**2+0.025*np.random.randn(200, 1)
tree_reg = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg.fit(X_quad, y_quad)</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/e3da5360-d012-4668-accf-a48a12c77c54/image.png" width = 80% disply =block margin = 4> </p>

<blockquote>
<p>최소화해야 하는 CART 비용 함수</p>
</blockquote>
<p>$$
J(k, t_k) = \frac{m_{left}}{m}G_{left}+\frac{m_{right}}{m}G_{right}
$$</p>
<p>여기서
$$
\bold{MSE_{node}} = \frac{1}{m_{node}}\sum_{i\in node}(\hat{y}<em>{node}-y^{(i)})^2
$$
$$
\hat{y}</em>{node} = \frac{1}{m_{node}}\sum_{i\in node}y^{(i)}
$$</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/fa57c512-2fa8-4815-baef-1ed63019961e/image.png" width = 80% disply =block margin = 4> </p>

<p>각 영역의 예측값은 항상 <strong>그 영역에 있는 타깃값의 평균</strong>이 된다. 알고리즘은 가능한 한 많은 샘플이 가까이 있도록 영역을 분할한다.</p>
<p>분류에서도 회귀 작업과 같이 결정 트리가 과대적합되기 쉽다는 것을 알 수 있다.</p>
<h1 id="🔥69-축-방향에-대한-민감성">🔥6.9 축 방향에 대한 민감성</h1>
<p>결정 트리는 <strong>계단 모양</strong>의 결정 경계를 만든다. (즉 모든 분할은 축에 수직이다.)
그래서 <strong>데이터 방향</strong>에 민감하다.</p>
<p>예를 들어 선형으로 구분될 수 있는 데이터셋을 보면,
만약 데이터를 45도 회전할 시, 트리의 경계가 구불구불해진다고 한다.
모두 완벽하게 학습하지만, 하나의 모델은 일반화가 잘 되지 않을 수 있다는 것이다...!</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/c2e5c481-e653-429b-93c6-eaf4af1544b8/image.png" width = 80% disply =block margin = 4> </p>

<blockquote>
<p>해결책 : PCA 변환 적용 (principal component analysis)</p>
</blockquote>
<p>데이터를 회전하여 결정 트리를 더 쉽게 만든다</p>
<p>직접 해보기</p>
<pre><code class="language-python">from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

pca_pipeline = make_pipeline(StandardScaler(), PCA())
X_iris_rotated = pca_pipeline.fit_transform(X_iris)
tree_clf_pca = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf_pca.fit(X_iris_rotated, y_iris)</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/549d4863-af73-4303-a3c2-087e6deea12e/image.png" width = 80% disply =block margin = 4> </p>
PCA 회전한 붓꽃 데이터셋에 대한 결정 트리의 경계



<h1 id="🔥610-결정-트리의-분산-문제">🔥6.10 결정 트리의 분산 문제</h1>
<blockquote>
<p>결정 트리의 주요 문제 : ❗<strong>분산이 상당히 크다는 것!</strong>❗</p>
</blockquote>
<p>이는 하이퍼파라미터나 데이터를 조금만 변경해도 매우 다른 모델이 생성될 수 있다는 것을 뜻한다. 이 훈련 알고리즘은 <strong>확률적</strong>이므로 동일한 결정 트리를 재훈련하더라도 (<code>random_state</code> 매개변수를 설정하지 않는 한) 매우 다른 모델이 생성될 수 있다.</p>
<blockquote>
<p>어떻게 해결하지? ❗<strong>여러 결정 트리</strong>❗를 이용하자!</p>
</blockquote>
<p>여러 결정 트리의 예측을 <strong>평균</strong>하면 분산을 크게 줄일 수 있고, 이러한 결정 트리의 앙상블이 그 유명한 ❗<strong>랜덤 포레스트</strong>❗이다. 현재 사용 가능한 가장 강력한 종류의 모델이다.</p>
<p>참고 도서 : 핸즈온 머신러닝 3판</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]5장 서포트 벡터 머신]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning5%EC%9E%A5-%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning5%EC%9E%A5-%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0</guid>
            <pubDate>Mon, 28 Oct 2024 06:48:57 GMT</pubDate>
            <description><![CDATA[<p>_뒷부분...수식이 많아서 따로 써야 하니...앞부분에 미리 광기를 담아 써야겠다. 나중에 봐도 이해할 수 있도록 써보았다...그리고...선형대수 열심히 더 해야겠다...</p>
<blockquote>
<p><strong>선형, 비선형 분류, 회귀, 특이치 탐지</strong>에도 쓸 수 있는 SVM! 골라 드세요!
주의 : 근데 데이터 많으면 별로...</p>
</blockquote>
<p>😗 근데 어느 정도여야 많다고 보는 거지?
👶 <strong>샘플이 수십만~수백만 개일 때</strong>, 차원이 수천 개 이상일 때! <em>인데 내가 그동안 해온 데이터들을 다 응애 수준이었구나... 컬럼 80개라 많다고 찡찡대던 거 반성하자...</em></p>
<p>수식 때문에 어질어질한 서포터 벡터 머신(support vetor machine, SVM)...너무 큰 데이터만 아니면 생각보다 다재다능하다...!</p>
<h3 id="장점">장점</h3>
<ul>
<li>고차원의 공간에서, 또는 차원 수가 샘플 수보다 많더라도 효과적으로 작동함</li>
<li>결정 함수에서 <strong>일부 훈련 포인트(=서포트 벡터)</strong>만 사용하기에 메모리 효율이 높다!</li>
<li>다양성이 높아 결정 함수에 대해 여러 종류의 커널 함수를 지정할 수 있다!<ul>
<li>일반적인 커널도 제공하지만, 직접 커널 🖌️커스텀도 가능하다!</li>
</ul>
</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>feature 수 &gt;&gt;&gt; sample 수<ul>
<li>커널 함수와 정규화 항을 잘 선택 → 과적합을 방지용</li>
</ul>
</li>
<li>확률 추정치를 안 줌!😶<ul>
<li>얻으려면 비용이 많이 드는 5겹 교차 검증을 사용해야 한다. (마치 깡통에서 시작하는 자동차 옵션을 보는 것만 같다...!)</li>
</ul>
</li>
</ul>
<p>본격적으로 정리 가보자고~</p>
<hr>
<p>선형부터 가자!</p>
<h1 id="51-선형-svm-분류">5.1 선형 SVM 분류</h1>
<p>🤓 결론 : 클래스 사이에 가장 폭이 넓은 도로를 찾는 것!
그래서 <strong>라지 마진 분류 (large margin classification)</strong>이라고 부른다.</p>
<p><img src="https://velog.velcdn.com/images/yoonie_03/post/54bbd891-ac08-4de7-aa26-be763d5aaea1/image.png" alt=""></p>
<p>누가봐도 데이터를 잘 구분할 수 있는 선이 그려진 그림은 오른쪽 그림이다. 이게 바로 SVM이다! </p>
<p><strong>실선</strong> : SVM 분류기의 결정 경계
<strong>점선</strong> : 점선은 각각의 결정 경계에서 가장 가까이 있는 점 주위의 선이라 보면 된다.</p>
<p>점선과 점선 사이의 폭이 마진으로, 앞으로 &#39;도로&#39;라고 표현할 것이다. SVM은 목적은 이 도로를 가장 넓게 만드는 경계를 찾는 것이다!</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/172174dd-71ef-406b-b5e9-532278e82f7f/image.png" width = 60% disply =block margin = 4> <a href="https://kr.mathworks.com/discovery/support-vector-machine.html" target="_blank">매트랩 Support vector machine이란?</a></p>




<p>SVM은 예측 시 도로를 위주로 보게 된다. 즉, 도로 바깥쪽에 열심히 샘플을 들이부어도 도로 경계에 위치한 샘플에 의해 결정된다. 이게 위에서 말한 <strong>일부 훈련 포인트</strong>로 이런 샘플을 <strong>서포트 백터(support vector)</strong>라고 한다. (훈련 포인트의 점들은 빨간 동그라미가 쳐진 것이다!)</p>
<h3 id="standardsclaer"><code>StandardSclaer</code></h3>
<p>SVM은 특성의 스케일에 민감하다. 더 넓은 도로를 만들기 위해 스케일을 조정한다고 보면 된다.</p>
<h2 id="1-소프트-마진-분류-vs-하드-마진-분류">1) 소프트 마진 분류 vs 하드 마진 분류</h2>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/2716c429-bd91-4aea-9834-8f10680cc40c/image.png" width = 100% disply =block margin = 4> <a href="https://scikit-learn.org/1.5/auto_examples/svm/plot_svm_margin.html" target="_blank">코드 참고</a></p>


<p>소프트와 하드의 차이점은 도로 폭을 볼 때 <strong>깐깐한 정도</strong>에 따라 구분할 수 있다!</p>
<p>🤔<strong>Hard</strong> : 모든 샘플이 도로 바깥쪽에 있어야 함! → 깐깐
😉<strong>Soft</strong> : Hard 보다는 좀 더 덜 깐깐하게! 적당히 균형을 잡은 것!</p>
<p>하드 마진 분류는 😗깐깐하기에 크게 두 문제점을 갖는다</p>
<ol>
<li>데이터는 <strong>선형적</strong>인 것으로 부탁해요~ 🙏</li>
<li><strong>이상치는 좀</strong>...^^ 🙏
<img src="https://velog.velcdn.com/images/yoonie_03/post/4c72a889-08b4-4466-bb8c-51d86920ce67/image.png" alt="">
<a href="https://colab.research.google.com/github/rickiepark/handson-ml3/blob/main/05_support_vector_machines.ipynb#scrollTo=z9Ua6w7f-7Uq">코드 참고</a></li>
</ol>
<p>이상치가 들어가면 최악의 경우
✅ 하드 마진 자체를 찾을 수 없거나! (왼쪽)
✅ 모델의 일반화가 잘 안 되게 된다! (오른쪽)</p>
<p><em><del>이럴거면 하드 마진 고르지도 않았지!!</del></em></p>
<p>이런 문제를 피하려면 좀 더 유연한 모델인 soft 버전을 쓰면 된다. </p>
<p>결국
✅ <strong>마진 오류 (margin violation)</strong> : 샘플이 도로 중간이나 반대쪽에 위치
✅ <strong>도로의 폭을 넓게</strong> 유지하는 것</p>
<p>이 두 가지 사이에 적절한 균형을 잡아야 하며, 
<strong>이를 소프트 마진 분류 (soft margin classification)</strong> 이라고 한다.</p>
<h2 id="2-규제-하이퍼-파라미터-c">2) 규제 하이퍼 파라미터 C</h2>
<p>뭐든 과하면 안 되니, 규제 역할도 필요하다! 이 역할은 c가 한다</p>
<table>
<thead>
<tr>
<th align="center">C : 커질게~ ⬆️</th>
<th align="center">구분</th>
<th align="center">C : 작아질게~⬇️</th>
</tr>
</thead>
<tbody><tr>
<td align="center">가자~ *<em>확장 *</em>공사!</td>
<td align="center">도로 폭</td>
<td align="center">자리없다~ <strong>줄이자</strong></td>
</tr>
<tr>
<td align="center">그렇게 늘리니까 <strong>마진 오류가 많지!</strong></td>
<td align="center">마진 오류</td>
<td align="center">그렇게 줄이니까 <strong>마진 오류가 없네?!</strong></td>
</tr>
<tr>
<td align="center">과대적합 주의!</td>
<td align="center">⚠️주의⚠️</td>
<td align="center">과소적합 주의!</td>
</tr>
</tbody></table>
<blockquote>
<p>직접 C=1인 선형 SVM 모델을 만들어 보겠다
사이킷런의 <code>LinearSVC</code>를 사용할 것이다.
Iris-Virginia 품종을 감지하기 위한 모델이다.</p>
</blockquote>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

iris = load_iris(as_frame=True)
X = iris.data[[&quot;petal length (cm)&quot;, &quot;petal width (cm)&quot;]].values
y = (iris.target == 2) # Irirs-Virginica

svm_clf = make_pipeline(StandardScaler(), 
                       LinearSVC(C=1, random_state =42)) # 
svm_clf.fit(X, y)</code></pre>
<p><img src="https://velog.velcdn.com/images/yoonie_03/post/cffa1ae3-9240-4828-9cc7-75cb5e105a57/image.png" alt=""> <del>있어 보이도록</del> 모델 구성을 잘 알 수 있게 해주는 파이프라인도 그렸다</p>
<pre><code class="language-python">X_new = [[5.5, 1.7], [5.0, 1.5]]
svm_clf.predict(X_new)
&gt;&gt;&gt; array([ True, False])</code></pre>
<p>첫 꽃은 Iris-Virginica로 분류되었지만, 두 번째 꽃은 아니다. </p>
<h2 id="3-성적표-공개가-깐깐한-svm">3) 성적표 공개가 깐깐한 SVM</h2>
<p>👨‍🏫 성적을 공개하기 위해 
<code>각 샘플과 결정 경계 사이의 거리(양수 또는 음수)</code>를 측정할게요~</p>
<pre><code class="language-python">svm_clf.decision_function(X_new)
&gt;&gt;&gt; array([ 0.66163411, -0.22036063]) # 거리 측정 완료~</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/2d217d82-ae70-4961-b36b-0680bf164837/image.gif" width = 20% disply =block margin = 4> </p>
<p align="center"> 이게 점...수? </p>

<p>로지스틱 회귀와 달리 <code>LinearSVC</code>에는 클래스 확률을 추정하는 <code>predict_proba()</code>메서드가 없다! </p>
<pre><code class="language-python">class sklearn.svm.LinearSVC(penalty=&#39;l2&#39;, 
loss=&#39;squared_hinge&#39;, *, dual=&#39;auto&#39;, tol=0.0001, C=1.0, 
multi_class=&#39;ovr&#39;, fit_intercept=True, intercept_scaling=1, 
class_weight=None, verbose=0, random_state=None, 
max_iter=1000)</code></pre>
<p>진짜 없다! (<a href="https://scikit-learn.org/dev/modules/generated/sklearn.svm.LinearSVC.html">공식문서</a> 레츠고~)</p>
<p>여기서 눈에 띄는 C를 잠깐 보자</p>
<blockquote>
<p><code>C : float, default=1.0</code>
Regularization parameter. The strength of the regularization is inversely proportional to C. Must be strictly positive. For an intuitive visualization of the effects of <strong>scaling the regularization parameter C</strong>, see Scaling the regularization parameter for SVCs.</p>
</blockquote>
<p>👶 점수를 안 줄 수가 있네 신기...</p>
<p>👨‍🏫 방법이 없진 않아요~(<a href="https://scikit-learn.org/dev/modules/svm.html#scores-probabilities">sklearn User Guide_SVM</a>)</p>
<p>step 1 ) <code>SVC</code> 클래스에서 <code>probability = True</code> 설정
step 2 ) 훈련 종료 전까지 SVM 결정 함수 점수를 추정 확률에 매핑하기 위해 추가적인 모델 훈련</p>
<p><strong>step 2 모델 훈련 과정)</strong></p>
<ul>
<li>5-fold 교차 검증을 사용하여 훈련 세트의 모든 샘플에 대해  표본 외 예측 생성</li>
<li>로지스틱 회귀 모델 훈련
→ <strong>정말 정말 오래 걸린다</strong></li>
</ul>
<p>step 3) 드디어 <code>predict_proba()</code> 및 <code>predict_long_proba()</code> 메서드 사용 가능...!</p>
<p>👶 이런 도른 놈들...!! <em><del>(마치 사과에서 과거 예약 메시지 걸려고 날뛰던 나같다)</del></em></p>
<hr>
<p>세상은 호락호락하지 않다! 많은 데이터는 비선형이지...!</p>
<h1 id="52-비선형-svm-분류">5.2 비선형 SVM 분류</h1>
<p>⭐이전 공략법⭐
→ 다항 특성을 이용!</p>
<p><img src="https://velog.velcdn.com/images/yoonie_03/post/43c1eedd-b46a-4f31-ab25-bdd34ba67ae2/image.png" alt=""></p>
<p>하나의 특성 $x_1$만 가지고 있다면 선형으로 구분할 수 없지만,
만약 두 번째 특성 $x_2 = (x_1)^2$ 을 추가한다면 2차원 데이터 셋을 선형적으로 구분할 수 있다!</p>
<h3 id="🌜make_moons🌛-이용해보기">🌜<code>make_moons()</code>🌛 이용해보기</h3>
<p><a href="https://scikit-learn.org/1.5/modules/generated/sklearn.datasets.make_moons.html">make_moons</a> : 두 개의 마주보는 반원을 만드는 함수, 비선형적인 분류, 군집이나 분류 알고리즘의 성능 시각화 및 실험에 유리하다.</p>
<ul>
<li>원문 설명을 보면 <code>interleaving</code>한 반원을 만든다고 설명하는데, 즉 서로 겹치며 얽혀 있는 형태를 만든다는 것이다. </li>
</ul>
<pre><code class="language-python">sklearn.datasets.make_moons(n_samples=100, *, shuffle=True,
noise=None, random_state=None)[source]</code></pre>
<p><code>noise</code> : 데이터에 추가되는 가우시안 노이즈의 강도(표준 편차), float값
→ 표준 편차가 클수록 데이터에 더 많이 날뛴다 생각하면 됨!(변동 많음)</p>
<pre><code class="language-python">from sklearn.datasets import make_moons
from sklearn.preprocessing import PolynomialFeatures

X, y = make_moons(n_samples=200, noise=0.15, random_state=42)

polynomial_svm_clf = make_pipeline(PolynomialFeatures(degree=3), #차수 3
                                  StandardScaler(),
                                   # 규제 10, 최대 반복 횟수 10000
                                  LinearSVC(C=10, max_iter=10000, random_state=42)) 

polynomial_svm_clf.fit(X, y)</code></pre>
<p><img src="https://velog.velcdn.com/images/yoonie_03/post/bafc9207-e541-4a84-b680-62a3395677e1/image.png" alt=""></p>
<h2 id="1-다항식-커널">1) 다항식 커널</h2>
<p>다항식 커널을 추가하는 것은 간단하고, 모든 머신러닝 알고리즘에서 잘 작동한다. 하지만 낮은 차수의 다항식은 복잡한 곳에는 쓰기 영 그렇고, 높은 차수는 모델을 느~리게 만든다. 🤔</p>
<p>그런데 SVM에서는 <del>사기행각</del> 수학적 방법을 이용할 수 있다.
<strong>실제 트릭을 추가하지도 않으면서 추가한 것과 같은 결과를 얻도록 해주는 것이다...!</strong></p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/44e17245-dc15-4ff3-bf56-a35bb2aa1dfe/image.gif" width = 20% disply =block margin = 4> 쩐다...!</p>

<p><code>SVC</code>에 이게 구현되어 있다. 테스트 하러 가보자고~</p>
<pre><code class="language-python">from sklearn.svm import SVC

poly_kernel_svm_clf = make_pipeline(StandardScaler(),
                                   SVC(kernel=&quot;poly&quot;, degree=3, coef0=1, C=5))
poly_kernel_svm_clf.fit(X, y)</code></pre>
<p><img src="https://velog.velcdn.com/images/yoonie_03/post/2428bf54-ddc8-4d76-b571-049b7be46526/image.png" alt=""></p>
<p><code>coef</code> : 모델이 차수에 얼마나 영향을 받을지 조절, 기본값 0</p>
<h3 id="svc의-kernel-항목"><code>SVC</code>의 <code>kernel</code> 항목</h3>
<pre><code class="language-python">kernel{‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’} 
or callable, default=’rbf’</code></pre>
<p>✅ <code>callable</code> : 호출 가능한 형태로 커널 지정 (=❗커스텀 커널❗)
✅ 커널 행렬은 $n \times n$ 형태의 배열이어야 함! 각 커널 행렬의 요소는 두 샘플 간의 <strong>유사도</strong>를 나타낸다.</p>
<h2 id="2-유사도-특성">2) 유사도 특성</h2>
<p>⭐이전 공략법⭐
→ <del>다항 특성을 이용!</del> 
→ <strong>랜드마크</strong> <del>건설</del> 이용!</p>
<blockquote>
<p><strong>유사도 함수(similarity function)</strong> : 랜드마크와 닮은 정도 측정
유사도 함수로 계산한 특성을 추가하면 비선형 데이터를 다룰 수 있다!</p>
</blockquote>
<p>👶 유사도 함수는 뭘 쓸건데
📢 가우스 방사 기저 함수 (<strong>R</strong>adial <strong>B</strong>asis** F**unction) 쓸거다!</p>
<p>👶 그게 무슨 역할 하는데
📢 0~1까지 변화하며 종 모양으로 변화며 🔔종 모양으로 나타난다! </p>
<p align="center">0 : 랜드마크에서 아주 멀리 떨어진 경우</p>
<p align="center">1 : 랜드마크와 같은 위치인 경우</p>

<p>$\gamma$= 0.3인 가우스 방사 기저 함수 적용시...</p>
<p>$x_1=-1$인 샘플이 
  랜드마크1에서는 1만큼,<br>  랜드마크 2에서는 2만큼 떨어져 있다면...</p>
<p>  $x_2 = e^{-0.3 ,\times1^2} \approx 0.74$,   $x_3 = e^{-0.3 ,\times2^2} \approx 0.30$</p>
<p>  아래 그림에서 오른쪽이 변환된 그림이다!</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/d496dfb3-42c9-45ec-942b-dec4d19ae13a/image.gif" width = 40% disply =block margin = 4> 👶 근데 랜드마크 어떻게 골라?</p>

<p align="center">📢 간단하게 데이터셋에 있는 모든 샘플 위치에 랜드마크를 설정하면 된다!</p>
<p align="center">👶 ??? 그럼 훈련 세트에 있는 n개의 특성을 가진 m개의 샘플이 m개의 특성을 가진 m개의 샘플이 되잖아...!!</p>

<p>그렇다...훈련 세트가 너무 많으면 추가되는 특성이 너무 많아진다...주의!</p>
<h2 id="3-가우스-형님의-rbf-커널">3) 가우스 <del>형님의</del> RBF 커널</h2>
<p>어지간히 중요한 부분이다. sklearnl공식 문서에서 SVM 부분에서 가장 먼저 나오는 항목이다...!</p>
<p>👶 유사도 특성 방법은 훈련 셍트가 너무 큰 경우에는 🤑연산 비용🤑이 너무 많이 들어가는데... 아까 본 그 <del>사기</del>가 아니라 커널 트릭을 쓰면 연산 비용을 아낄 수 있지 않을까?!</p>
<blockquote>
<p>실제로 해보기
 <code>gamma</code> : <strong>규제</strong>의 역할 담당!</p>
</blockquote>
<p>😉 증가할게~  ➡️ 종 모양 그래프 좁아짐, 각 샘플의 영향 범위 ↓, 결정 경계 더 불규칙해지고 각 샘플을 따라 구불구불 휘어진다...!
➡️ <strong>과소적합</strong> 때 사용!</p>
<p>😉 감소할게~  ➡️ 넓은(<del>flex</del>) 종 모양, 샘플이 넓은 버무이에 걸쳐 영향 주어서 결정 경계가 부드러워짐
➡️ <strong>과대적합</strong> 때 사용!</p>
<p>모델의 복잡도를 조절할 땐 $\gamma$만 조절하기 보다는 <code>C</code>와 함께 조절해 주는 것이 좋음! </p>
<blockquote>
<p>✅ 다른 커널들</p>
</blockquote>
<p>도 존재는 하지만 잘 안 쓴다!
다만 <strong>문자열 커널(string kernel)</strong>과 같이 특정 데이터 구조에 특화되어 있으면 쓴다. 텍스트 문서나 DNA 서열 분류에 이용된다.</p>
<p>✔️ string subsequence kernel
✔️ Levenshtein distance
🔗 <a href="https://goo.gl/6eb3f2">궁금하면 여기로</a></p>
<blockquote>
<p>👶 이렇게 커널이 많은데 뭘 써야하지</p>
</blockquote>
<p>1) 선형 커널 first (<code>LinearSVC</code>가 <code>SVC(kernel=&quot;linear&quot;)</code>보다 빠름!) 
: 일단 훈련 세트가 아주 큰(샘플 수만 개 정도) 경우에 유리 
2) 👶 훈련 세트 좀 작은데(샘플 수천 개 정도) ? ➡️ RBF 커널 시도, 정확도 👍</p>
<h2 id="4-계산-복잡도">4) 계산 복잡도</h2>
<p>일단 정말 여러 알고리즘이 나왔는데...헷갈리니까 정리해보자.</p>
<p>✅ <code>LinearSVC</code>  🔗<a href="https://scikit-learn.org/dev/modules/generated/sklearn.svm.LinearSVC.html">sklearn 공식문서</a></p>
<ul>
<li>선형 SVM을 위한 최적화된 알고리즘을 구현한 <code>liblinear</code><a href="https://github.com/cjlin1/liblinear">라이브러리</a> 기반</li>
<li>커널 트릭 ❌ </li>
<li>훈련 샘플과 특성 수에 선형적으로 늘어남, 정밀도 높이면 수행 시간 ⬆️</li>
<li>허용 오차 파라미터 ε(앱실론)로 조절!<ul>
<li><code>tol</code> : float, 기본값 <strong>0.0001</strong>, 알고리즘 종료 조건에 대한 허용 오차</li>
<li>대부분의 문제는 허용 오차를 기본값으로 두면 잘 작동! </li>
</ul>
</li>
</ul>
<p>✅ <code>SVC</code> 🔗 <a href="https://scikit-learn.org/1.5/modules/generated/sklearn.svm.SVC.html">sklearn 공식문서</a></p>
<ul>
<li>커널 트릭 알고리즘을 구현한 <code>libsvm</code> <a href="https://github.com/cjlin1/libsvm">라이브러리</a> 기반</li>
<li>훈련 샘플이 많으면 <strong>너무 느려요...</strong> ➡️ <strong>중소규모 비선형 훈련 세트에</strong> 최적!</li>
<li>tol` : float, 기본값 <strong>0.001</strong>, 알고리즘 종료 조건에 대한 허용 오차</li>
<li>❗희소 특성(sparse feature)❗인 경우에 잘 확장!!<ul>
<li>👶 희소 특성이 뭔데 : <strong>샘플에 0이 아닌 특성이 몇 개 없는 경우</strong></li>
<li>알고리즘 성능이 샘플이 가진 0이 아닌 특성의 <strong>평균 수에 거의 비례</strong></li>
</ul>
</li>
</ul>
<p>✅ <code>SGDClassifier</code> 🔗 <a href="https://scikit-learn.org/dev/modules/generated/sklearn.linear_model.SGDClassifier.html">sklearn 공식문서</a></p>
<ul>
<li>라지 마진 분류 수행</li>
<li>훈련을 위한 점진적 학습 가능, 메모리 거의 사용 ❌ ➡️ 대규모 데이터셋 학습 가능(외부 메모리 학습 가능)</li>
<li>확장성이 뛰어남!</li>
</ul>
<table>
<thead>
<tr>
<th align="left">pyhton class</th>
<th align="left">시간 복잡도</th>
<th align="center">외부 메모리 지원</th>
<th align="center">스케일 조정 필요</th>
<th align="center">커널 트릭</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>LinearSVC</code></td>
<td align="left">$O(m,\times n)$</td>
<td align="center">❌</td>
<td align="center">⭕</td>
<td align="center">❌</td>
</tr>
<tr>
<td align="left"><code>SVC</code></td>
<td align="left">$O(m^2,\times n) \sim O(m^3,\times n)$</td>
<td align="center">❌</td>
<td align="center">⭕</td>
<td align="center">⭕</td>
</tr>
<tr>
<td align="left"><code>SGDClassifier</code></td>
<td align="left">$O(m,\times n)$</td>
<td align="center">⭕</td>
<td align="center">⭕</td>
<td align="center">❌</td>
</tr>
</tbody></table>
<hr>
<p>이제 회귀할 시간이다!</p>
<h1 id="53-svm-회귀">5.3 SVM 회귀</h1>
<p>회귀를 위해서는 목표 수정이 필요하다
⭐ 기존 목표 : 일정한 마진 오류 안에서 두 클래스 간의 도로 폭 최대로 만들기</p>
<p align="center">⬇️</p>

<p>⭐ 새로운 목표 : 제한된 마진 오류(도로 밖 샘플) 아네어 도로 안에 가능한 한 많은 샘플이 들어가도록 학습 (도로 폭은 <strong>ε(=마진)</strong>으로 조절!</p>
<h3 id="🙃-ε을-조절해보자">🙃 ε을 조절해보자</h3>
<p align="center"> ε : 감소할게~ ⬇️ </p>

<p>→ 서포트 벡터 수 ⬆️ = 경계에서 예측에 영향 주는 정도 ⬆️
→ 모델 규제
→ 마진 안에서 훈련 샘플이 추가되어도 예측 영향 NO!
= <strong>ε에 민감하지 않다(ε-insensitive)</strong></p>
<blockquote>
<p>이름이 비슷한 데에는 이유가 있다 </p>
</blockquote>
<p><code>SVR</code>는 <code>SVC</code> 회귀 ver. (훈련 세트가 커지면 훨씬 느려짐!)
<code>LinearSVR</code>는 <code>LinearSVC</code> 회귀 ver. (시간이 선형적으로 늘어남!)</p>
<blockquote>
<p><a href="https://scikit-learn.org/1.5/modules/svm.html#regression">SVM Regression</a>
<a href="https://scikit-learn.org/1.5/auto_examples/svm/plot_svm_regression.html#sphx-glr-auto-examples-svm-plot-svm-regression-py">예시</a></p>
</blockquote>
<h1 id="54-svm-이론">5.4 SVM 이론</h1>
<p>따로 <a href="https://velog.io/@yoonie_03/ML-SVM-%EC%9D%B4%EB%A1%A0">다른 링크</a>에서 다루었다...수식 살려줘</p>
<h1 id="55-쌍대-문제">5.5 쌍대 문제</h1>
<p>따로 <a href="https://velog.io/@yoonie_03/optimization-Dual-Problem">다른 링크</a>에서 다루었다2 수식 어려워요</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]4장 모델 훈련]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning4%EC%9E%A5-%EB%AA%A8%EB%8D%B8-%ED%9B%88%EB%A0%A8</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning4%EC%9E%A5-%EB%AA%A8%EB%8D%B8-%ED%9B%88%EB%A0%A8</guid>
            <pubDate>Tue, 01 Oct 2024 01:13:18 GMT</pubDate>
            <description><![CDATA[<p>오늘은 4장 모델 훈련에 대해 정리하려고 한다. 수식적인 내용은 따로 더 알아보고 싶어서 이번엔 치대한 간결하게 내용만 정리했다.</p>
<h1 id="🔥41-선형-회귀">🔥4.1 선형 회귀</h1>
<ul>
<li>선형 회귀 방정식을 정리하면 아래와 같다</li>
</ul>
<p>$$
\hat{y} = \theta_0 +\theta_1 x_1 + \cdots + \theta_n x_n
$$</p>
<p>$\hat{y}$는 예측된 값
$n$은 feature 개수
$x_i$는 i번째 feature 값
$\theta_j$는 j번째 모델의 파라미터</p>
<p>이 식을 벡터화된 식으로 정리하면 아래와 같다</p>
<p>$$
\hat{y} = \theta_0(\textbf{x})=\boldsymbol{\theta} ,\cdot \textbf{x}
$$</p>
<p>$\boldsymbol{\theta}$는 모델의 파라미터 벡터다. 
편향인 $\theta_0$를 포함하며 feature의 가중치 $\theta_1$부터 $\theta_n$을 포함한다</p>
<p>$\textbf{x}$는 instance(데이터 인스턴스 또는 샘플)의 feature vector다. 
$x_0$ 부터 $x_n$를 포함하며, $x_0$은 1이다</p>
<p>$\boldsymbol{\theta} ,\cdot \textbf{x}$는 $\boldsymbol{\theta}$와 $\textbf{x}$ 간의 외적이다.
$\theta_0 x_0 +\theta_1 x_1 + \cdots + \theta_n x_n$ 값을 의미한다</p>
<p>$h_\theta$는 <code>hypothesis function</code>(입력 데이터에 대한 예측을 수행하는 가설 함수)이며, 모델 파라미터 $\boldsymbol{\theta}$를 사용한다</p>
<blockquote>
<p>모델을 훈련시키기 위해 RMSE 방식이나 MSE 방식을 사용한다</p>
</blockquote>
<p>훈련 집합 $\textrm{X}$에 대한 선형 회귀 가설 함수 $h_\theta$를 계산하려면 아래 식을 이용할 수 있다.</p>
<p>$$
\textbf{MSE}(\textrm{X},h_\theta) = \frac{1}{m} \sum_{i=1}^{m}(\boldsymbol{\theta}^T \textbf{x}^{(i)} - \textbf{y}^{(i)})^2
$$</p>
<p>파라미터 값을 담은 $\boldsymbol{\theta}$를 최소화 하는 비용함수를 구하기 위해 여러 방법이 있다. 명확한 수식으로 구하는 방법(닫힌 형태의 해)이 있다. 이 식을 <strong>Normal Equation(정규화 식)</strong>이라 한다.</p>
<p><em>Normal Equation</em>
$$
\hat{\boldsymbol{\theta}} = (\textrm{X}^{\textrm{T}}\textrm{X})^{-1}
$$</p>
<p>$\hat{\boldsymbol{\theta}}$는 비용 함수를 최소화 한 $\boldsymbol{\theta}$값
$\textrm{y}$는 $y^{(1)}$부터 $y^{(m)}$를 포함하는 타겟값</p>
<p>해를 구할 때 유사역행렬을 이용하는데, 이는 SVD를 이용하면 쉽게 구할 수 있음.</p>
<h1 id="🔥42-경사-하강법">🔥4.2 경사 하강법</h1>
<p>여러 종류에서 최적의 해법을 찾을 수 있는 일반적인 최적화 알고리즘</p>
<p>학습률 : 파라미터 스텝의 크기, 한 번에 내려가게 되는 정도라 생각하면 될 것 같다! 너무 작으면 전역 최솟값 도달 힘듦. 너무 크면 수렴안할 수 있어서 적당한 값 선택 필수</p>
<p>특성 스케일을 적용해야 빠르게 도달한다고 함
(x,y축을 같은 크기로 만들어준다 생각)</p>
<h3 id="421-배치-경사-하강법">4.2.1 배치 경사 하강법</h3>
<p>비용 함수가 얼마나 바뀌는지 계산 : 편도함수
적절한 학습률을 찾기 위해 그리드 서치 이용</p>
<p>하지만 그리드 서치는 수레기...느려
반복 횟수를 제한하면 되는데 이때 반복 횟루를 아주 크게 지정하고 그레이디언트 벡터가 아주 작아지면, 즉 벡터의 노름이 어떤 허용오차라 불리는 값보다 작아지면 중지하면 된다. 이렇게 허용오차보다 작아지면 경사 하강법이 거의 최솟값에 도달한 것이라 볼 수 있음.</p>
<h3 id="422-확률적-경사-하강법">4.2.2 확률적 경사 하강법</h3>
<p>매 스텝에서 한 개의 샘플을 랜덤으로 선택하고, 그 샘플에 대한 그레이디언트 계산한다. 랜덤으로 고르기에 훨씬 불안정하고 마구 요동치게 된다. 무엇보다 최솟값에 안착은 못한다. 하지만 전역 최솟값을 찾을 가능성이 높고 외부 메모리 학습이 가능한 등 장점이 많다</p>
<h3 id="423-미니배치-경사-하강법">4.2.3 미니배치 경사 하강법</h3>
<p>확률적 경사 하강법에서 한 개의 샘플이 아닌 미니 배치라 불리는 임의의 작은 샘플 세트를 고른다 보면 된다.</p>
<h1 id="🔥43-다항-회귀">🔥4.3 다항 회귀</h1>
<p>다항 함수를 그려서 예측을 할 수 있다고 보면 된다.
각 특성의 거듭제곱을 새로운 특성으로 추가하고, 이 확장된 특성을 포함한 데이터셋에 선형 모델 훈련시키면 된다.</p>
<h1 id="🔥44-학습-곡선">🔥4.4 학습 곡선</h1>
<p>고차 다항 회귀 → 훈련 데이터 과대적합 ↑</p>
<p>성능 ↑ 교착 검증 점수 ↓ → 과대적합
성능 ↓ 교착 검증 점수 ↓ → 과소적합</p>
<p>과대적합 모델 개선하려면 검증 오차가 훈련 오차에 근접할 때까지 더 많은 훈련 데이터를 추가하는 것!</p>
<h1 id="🔥45-규제가-있는-선형-모델">🔥4.5 규제가 있는 선형 모델</h1>
<h3 id="릿지-회귀">릿지 회귀</h3>
<blockquote>
<p>규제가 추가된 선형 회귀 버전, 훈련하는 동안에만 비용 함수에 추가된다.</p>
</blockquote>
<p>릿지 회귀의 정규 방정식
$$
\hat{\boldsymbol{\theta}} = (\textrm{X}^{\textrm{T}}\textrm{X}+\alpha\textrm{A})^{-1}\textrm{X}^{\textrm{T}}\textrm{y}
$$</p>
<h3 id="라쏘-회귀">라쏘 회귀</h3>
<blockquote>
<p>선형 회귀의 또 다른 규제 버전, 릿지 회귀처럼 비용 함수에 규제항을 더하지만 $l2$ 노름 대신 $l1$ 노름 사용</p>
</blockquote>
<p>덜 중요한 특성의 가중치를 제거하려고 함. 
즉 자동으로 특성을 수행하고 희소 모델을 만든다.</p>
<p>*라쏘의 비용 함수는 $\theta_i =0$일 때 서브그레이디언트 벡트 $\textrm{g}$를 사용하면 경사하강법을 적용하는데 문제가 안 든다.</p>
<h3 id="엘라스틱넷-회귀">엘라스틱넷 회귀</h3>
<blockquote>
<p>릿지 회귀와 라쏘 회귀를 절충한 모델</p>
</blockquote>
<p>규제항 : 릿지와 휘괴의 규제항을 더한 것, 혼합 정도는 혼합 비율 r을 이용해 조절
r=0 → 릿지 회귀
r=1 → 라쏘 회귀</p>
<p>일단 평범한 선형 모델은 피하고, 릿지기 기본이 되지만 몇 가지 특성만 유용해 보이면 라쏘나 엘라스틱넷 선택! 특성 수가 훈련 샘플 수보다 많거나 특성 몇 개가 강하게 연관되어 있을 때는 라쏘보다는 엘라스틱넷 이용!</p>
<h3 id="조기-종료early-stopping">조기 종료(early stopping)</h3>
<blockquote>
<p>검증 오차가 최솟값에 도달하면 바로 훈련을 중지시키는 것</p>
</blockquote>
<p>제프리 힌턴이 &#39;훌륭한 공짜 점심&#39;이라고 부름
생각보다 효과가 크다고 한다.</p>
<h1 id="🔥46-로지스틱-회귀">🔥4.6 로지스틱 회귀</h1>
<blockquote>
<p>샘플이 특정 클래스에 속할 확률을 추정하는데 이용
임곗값(보통 50%) 크면 양성 클래스(label=1), 작으면 음성 클래스(label=0)</p>
</blockquote>
<h3 id="461-확률-추정">4.6.1 확률 추정</h3>
<p>선형 회귀 모델과 같이 입력 특성의 가중치 합 계산 + 편향
선형 회귀 처럼 바로 결과 출력이 아닌 로지스틱 출력</p>
<p>로지스틱 : 0과 1 사이의 값을 출력하는 시그모이드 함수</p>
<h3 id="462-훈련과-비용-함수">4.6.2 훈련과 비용 함수</h3>
<p>모델의 파라미터 벡터를 찾는 것</p>
<p>로그 손실 : 전체 훈련 세트에 대한 비용 함수는 모든 훈련 샘플의 비용을 평균한 것
로그 손실은 최적해가 없지만 convex라 경사 하강법으로 전역 최솟값을 구할 수 있음.</p>
<h3 id="463-결정-경계">4.6.3 결정 경계</h3>
<ul>
<li>선형으로 나타남</li>
<li>다른 선형 모델처럼 로지스틱 회귀 모델도 l1, l2 패널티 사용하여 규제 가능, 사이킷런은 l2 패널티를 기본으로 함</li>
</ul>
<h3 id="464-소프트맥스-회귀">4.6.4 소프트맥스 회귀</h3>
<p>로지스틱 회귀 모델은 이진 분류기를 훈련시켜 연결하지 않고 직접 다중 클래스 지원하도록 일반화 가능</p>
<blockquote>
<p>이를 소프트맥스 회귀 또는 다항 로지스틱 회귀라 부름</p>
</blockquote>
<p>방법 : 샘플 x가 주어지면 소프트맥스 회귀 모델이 각 클래스에 대한 점수를 계산하고, 그 점수에 소프트맥스 함수(정규화된 지수 함수)를 적용하여 각 클래스의 확률을 추정함.</p>
<p>각 클래스는 자신만의 파라미터 벡터가 있고, 이 벡터들은 <strong>파라미터 행렬</strong>에 행으로 저장된다.</p>
<p>&quot;모델이 타깃 클래스에 대해서는 높은 확률을, 다른 클래스에서는 낮은 확률이 추정되도록 만드는 것이 목적&quot; → 크로스 엔트로피 비용 함수를 최소화 하는 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]3장 분류]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning3%EC%9E%A5-%EB%B6%84%EB%A5%98-yohaccgq</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning3%EC%9E%A5-%EB%B6%84%EB%A5%98-yohaccgq</guid>
            <pubDate>Mon, 23 Sep 2024 19:05:57 GMT</pubDate>
            <description><![CDATA[<p>어느덧 핸즈온 머신러닝도 3장 째다. 드디어 본격적으로 머신러닝 기법에 대해서 학습한다! 먼저 분류, 즉 Classification에 대해서 다루어 보려고 한다. 지금부터는 나중에 해당 주제에 대한 내용을 한 번에 몰아볼 수 있도록 글을 나누어 작성하려고 한다. <em>필요한 부분만 찾아서 읽기에 이런 방법이 좋을 것 같아 택한다...</em></p>
<h1 id="🔥31-mnist">🔥3.1 MNIST</h1>
<p><strong>MNIST dataset</strong>은 70,000개의 이미지로 이루어진 데이터셋이다. 머신 러닝계의 <em>&quot;Hello world&quot;</em> 급의 데이터셋이라 보면 된다.</p>
<p>Scikit-Learn에서 MNIST dataset을 다운로드할 수 있도록 제공한다.</p>
<pre><code class="language-python">from sklearn.datasets import fetch_openml

#데이터 로드
mnist = fetch_openml(&#39;mnist_784&#39;, version=1)
mnist.keys()</code></pre>
<p><code>dict_keys([&#39;data&#39;, &#39;target&#39;, &#39;frame&#39;, &#39;categories&#39;, &#39;feature_names&#39;, &#39;target_names&#39;, &#39;DESCR&#39;, &#39;details&#39;, &#39;url&#39;])</code> 라는 결과가 나오는 것을 확인할 수 있다.</p>
<pre><code class="language-python"># 데이터의 형상 출력
print(X.shape)
print(y.shape)</code></pre>
<p><code>(70000, 784)
(70000,)</code> 결과를 확인할 수 있다.</p>
<p>70000개의 이미지는 784개의 픽셀을 가진다. 왜냐하면 28<em>28 pixcel로 이루어졌기 때문이다. 각각의 feature는 하나의 픽셀의 강도를 나타내며, 강도는 *</em>0(white)<strong>에서 **255(black)</strong>까지의 범위를 가진다.</p>
<p><code>matplotlib</code>의 <code>imshow()</code> 함수를 이용해서 예시로 이미지를 하나 가져오겠다.</p>
<pre><code class="language-python">import matplotlib as mpl
import matplotlib.pyplot as plt

# 일부 숫자 이미지 가져오기
some_digit = X.iloc[0].values
some_digit_image = some_digit.reshape(28, 28)

# 이미지 출력
plt.imshow(some_digit_image, cmap=mpl.cm.binary, interpolation=&quot;nearest&quot;)
plt.axis(&quot;off&quot;)
plt.show()

print(&quot;label :&quot;,y.iloc[0]) #라벨링 된 결과 확인</code></pre>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/fe9a7f9a-b11a-4c95-a9c5-d16108b88663/image.png" width = 40% disply =block margin = 4> </p>

<p>그림을 보면 숫자 5처럼 보이며, 실제 라벨링도 &#39;5&#39;라고 되어 있는 것을 확인할 수 있다.</p>
<p>항상 시작하기 전에 훈련데이터과 테스트 데이터을 나누어 주어야 한다. <strong>MNIST</strong> 데이터셋은 이미 앞의 6만 개가 훈련 데이터, 뒤의 1만 개가 테스트 데이터이다. 훈련 데이터는 이미 잘 섞여 있기에 후에 교차 검증(cross-validation)이나 각 폴드(fold)의 데이터의 분포를 고르게 반영할 수 있도록 보장해준다. 간혹 특정 learning algorithms이 훈련 데이터의 순서에 민감한 경우, 성능이 떨어지게 된다.</p>
<h1 id="🔥32-이진-분류기-훈련">🔥3.2 이진 분류기 훈련</h1>
<p>상황을 조금 단순하게 만들어보자. 숫자 5가 맞는지, 맞지 않는지 판단하는 이진 분류기(binary classifier)를 만들어 볼 것이다.</p>
<pre><code class="language-python">y_train_5 = (y_train == 5) #True for all 5s, False for all other digits.
y_test_5 = (y_test == 5)</code></pre>
<p>SGD(Stochastic Gradient Descent), 확률적 경사 하강법을 이용할 것이며, <code>Scikit-Learn</code>의 <code>SGDClassifier</code>을 이용할 것이다. 확률적 경사 하강법은 빠른 데이터셋이라도 효율적으로 처리가 가능하다.</p>
<pre><code class="language-python">some_digit = X.iloc[0].values

from sklearn.linear_model import SGDClassifier

sgd_clf = SGDClassifier(random_state = 42)
sgd_clf.fit(X_train, y_train_5)
sgd_clf.predict([some_digit]) # 첫 번째 데이터 5인지 판별</code></pre>
<p><code>array([ True])</code>라는 결과가 나오는 것을 확인할 수 있다.</p>
<h1 id="🔥33-성능-평가">🔥3.3 성능 평가</h1>
<blockquote>
<p>classifier을 평가하는 것은 regressor를 평가하는 것보다 훨씬 까다로운 경우가 많다. 이 주제에 대해 많은 얘기를 할 것이다.</p>
</blockquote>
<h3 id="331-교차-검증을-통한-정확도-측정">3.3.1 교차 검증을 통한 정확도 측정</h3>
<p><strong>교차 검증</strong>은 데이터의 편중을 막기 위해 데이터를 여러 부분으로 나누어 각각의 부분을 학습 및 검증에 사용하는 방법이다.</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/26b0e6bf-f715-4ed2-96d0-bd406d8071fb/image.png" width = 80% disply =block margin = 4> </p>

<p>Scikit-Learn에서는 <code>cross_val_score()</code> 함수를 이용해서 교차 검증 기법을 활용해서 정확도를 측정할 수 있다. y가 이진 클래스 또는 다중 클래스인 경우 이 함수는 <code>StratifiedKFold</code>를 사용한다. 다른 모든 경우, 예를 들어 회귀 문제나 다중 출력 회귀 문제인 경우에는 KFold가 사용된다. </p>
<p>해당 함수의 매개변수 중 <code>cv</code>는 정수값을 넣을 수 있다. 기본값은 5이다. </p>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html">cross_val_score : sk-learn 공식 문서</a></p>
<blockquote>
<p><a href="https://velog.io/@yoonie_03/ML-K-fold-vs-StratifiedKFold"><strong>StratifiedKFold</strong>와 <strong>K-fold</strong>의 차이점</a></p>
</blockquote>
<h3 id="332-confusion-matrix-혼동행렬">3.3.2 Confusion Matrix (혼동행렬)</h3>
<h3 id="333-정밀도와-재현율">3.3.3 정밀도와 재현율</h3>
<h3 id="334-정밀도재현율-트레이드-오프">3.3.4 정밀도/재현율 트레이드 오프</h3>
<p>위의 내용은 이전 블로그 글에 잘 정리해 두었다.</p>
<blockquote>
<p><a href="https://velog.io/@yoonie_03/Confusion-Matrix%EC%99%80-%EC%9D%B4%EC%9A%A9">Confusion Matrix와 이용</a></p>
</blockquote>
<h3 id="335-roc-곡선">3.3.5 ROC 곡선</h3>
<p>위의 내용은 이전 블로그 글에 잘 정리해 두었다.</p>
<blockquote>
<p><a href="https://velog.io/@yoonie_03/ML-ROC-Curve">ROC Curve</a></p>
</blockquote>
<h1 id="🔥34-다중-분류">🔥3.4 다중 분류</h1>
<p>2개 이상의 클래스로 분류하는 것을 다중 분류라고 한다.</p>
<p><strong>Random Forest classifiers</strong>와 <strong>Bayes classifiers = multinomial classifiers</strong>의 경우, 다중 분류가 가능하다.</p>
<p>하지만 <strong>Support Vector Machine classifiers</strong>와 <strong>Linear classifiers</strong>는 이진 분류에만 한정된다. 하지만 여러 개의 이진 분류기를 통해 다중 분류하는 것도 가능하다.</p>
<p>다중 분류에는OvA(<strong>One-versus-all</strong>) 전략과 OvO(<strong>One-versus-one</strong>)이 있다.
다중 분류에 관한 내용은 이전 블로그 글에 잘 정리해 두었다.</p>
<blockquote>
<p><a href="https://velog.io/@yoonie_03/ML-Multiclass-Classification">Multiclass Classification</a></p>
</blockquote>
<h1 id="🔥35-오류-분석">🔥3.5 오류 분석</h1>
<p>모델 성능을 개선하고자 할 때 흔히 사용하는 방법이 있다. 바로 error를 분석하는 것이다.</p>
<blockquote>
<p><strong>혼동 행렬(Confusion Matrix)</strong> 이용해서 분석</p>
</blockquote>
<p>sk-learns에서는 <code>cross_val_predict()</code>을 이용해서 예측값을 구한 후, <code>confusion_matrix()</code>을 이용해서 쉽게 구할 수 있다.
또한 matplotlib의 <code>matshow()</code>함수를 이용해서 이를 시각화 할 수 있다. 분류가 잘 되었다면 메인 대각선이 잘 보일 것이다. </p>
<p>TIP! 오차 행렬을 컬러 그래프로 나타내면 분석하기가 훨씬 쉽다.
이럴 땐 <code>ConfusionMatrixDisplay.from_predictions()</code> 함수를 이용해 주면 된다!</p>
<blockquote>
<p>주의!! 오차 행렬에서 백분율 해석하는 방법</p>
</blockquote>
<p><strong>올바른 예측</strong>을 제외했다는 점을 기억해야 한다.</p>
<p><em>예를 들어 7번 행, 9번 열의 36%는 모든 7 이미지 중 36%가 9로 잘못 분류된 것이 아니라 7 이미지에서 발생한 오류 중 36%가 9라고 잘못 분류 되었다는 것이다! 참고로 오차 행렬은 대칭으로 나타나지 않는다!</em></p>
<h1 id="🔥36-다중-레이블-분류">🔥3.6 다중 레이블 분류</h1>
<p><a href="https://velog.io/@yoonie_03/ML-Multilabel-classification">Multilabel classification</a></p>
<h1 id="🔥37-다중-출력-분류">🔥3.7 다중 출력 분류</h1>
<p>하나의 입력에 대해 여러 개의 예측값을 동시에 출력하는 분류 문제</p>
<blockquote>
<p><strong>다중 출력 다중 클래스 분류 (multioutput-multiclass classification)
다중 출력 분류 (multioutput classification)</strong>
두 용어는 같은 말이다.</p>
</blockquote>
<p>다중 레이블 분류에서 한 레이블이 다중 클래스가 될 수 있도록 일반화 한 것이다. <strong>다중 레이블 분류 + 다중 클래스 분류</strong>가 합쳐진 형태로 보면 될 것 같다. <em>끝판왕인 느낌?</em></p>
<h3 id="1-다중-레이블과의-차이점">1) 다중 레이블과의 차이점</h3>
<p>다중 레이블 분류와는 다소 비슷하지만, 다중 출력 분류는 여러 레이블이 서로 다른 유형의 출력을 가질 수 있다.</p>
<h3 id="2-활용">2) 활용</h3>
<p>다중 출력 분류는 <strong>여러 개의 종속 변수(레이블)</strong>를 예측하는 문제를 해결하는 데 사용되며, 각 레이블이 서로 독립적이지 않을 수 있다. 이러한 방식은 하나의 입력에서 여러 결과를 동시에 예측해야 할 때 유용하다.</p>
<p><strong>1. 자율주행 차량의 신호등 상태 및 차선 위치 예측</strong></p>
<ul>
<li>자율 주행 차량이 주변 환경을 인식할 때, 차량 신호등 상태(3가지)와 차선 위치(차선 유지, 이탈 여부 등)도 예측해야 한다면<ul>
<li>출력 1: 신호등 상태 (빨강, 노랑, 초록)
출력 2: 차선 상태 (정상 차선 유지, 차선 이탈)</li>
</ul>
</li>
</ul>
<p><strong>2. 의료 이미지 분석</strong></p>
<ul>
<li>하나의 흉부 X-ray 이미지를 분석할 때 여러 장기나 신체 부위 상태를 각각 예측할 수 있어야 한다!</li>
<li>출력 1: 폐 상태 (정상, 폐렴, 결핵)
  출력 2: 심장 상태 (정상, 비대, 기능 저하)</li>
</ul>
<p><strong>3. 자연어 처리(NLP)</strong></p>
<ul>
<li>출력 1: 감정 분석 (긍정, 중립, 부정)</li>
<li>출력 2: 주제 분류 (정치, 경제, 스포츠)</li>
</ul>
<p><strong>4. 이미지 태그 및 속성 분류</strong></p>
<ul>
<li>출력 1: 의류 종류 (셔츠, 바지, 코트)</li>
<li>출력 2: 색상 (빨강, 파랑, 녹색)</li>
<li>출력 3: 스타일 (캐주얼, 포멀)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] Multilabel classification]]></title>
            <link>https://velog.io/@yoonie_03/ML-Multilabel-classification</link>
            <guid>https://velog.io/@yoonie_03/ML-Multilabel-classification</guid>
            <pubDate>Mon, 23 Sep 2024 18:46:23 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>회귀의 한 종류인 다중 라벨 분류에 대해 정리하려고 한다</p>
</blockquote>
<p>분류기가 샘플마다 <strong>여러 개</strong>의 클래스를 출력해야할 때가 있다, 이럴 때 사용되는 것이 바로 다중 레이블 분류다!</p>
<p> 다중 레이블의 예시를 찾아보면 아래와 같다! 생각보다 다양하다.</p>
<ul>
<li>음악 장르 분류<ul>
<li>한 곡이 &#39;재즈&#39;, &#39;블루스&#39; 등 여러 장르로 분류될 수 있다.</li>
</ul>
</li>
<li>영화 태그 분류<ul>
<li>한 영화가 &#39;액션&#39;, &#39;SF&#39; 등 여러 장르에 속할 수 있으며, &#39;범죄수사물&#39;, &#39;&#39; 등 다양한 태그를 가질 수 있다!</li>
</ul>
</li>
<li>의료 진단<ul>
<li>환자가 여러 질병을 동시에 가질 수 있기에 의료 진단 역시 다중 레이블 분류다!</li>
<li>한 환자가 &#39;고혈압&#39;, &#39;당뇨&#39; 등 여러 질환을 동시에 진단 받을 수 있다.</li>
</ul>
</li>
<li>텍스트 분류<ul>
<li>블로그 게시물, 뉴스 기사 등 여러 가지 주제를 동시에 할당할 수 있다.</li>
<li>뉴스 카테고리 분류를 생각하면 좋을 것 같다! 한 기사가 &#39;정치&#39;, &#39;경제&#39; 등 여러 개의 카테고리에 속할 수 있다.</li>
</ul>
</li>
</ul>
<p>만약 &#39;정치&#39;, &#39;경제&#39;, &#39;사회&#39; 세 가지 카테고리에 따라 뉴스 기사를 분류하도록 훈련된 분류기가 있다고 해보자. 만약 정치와 사회 카테고리에 속하는 기사를 본다면 <strong>[1, 0, 1]</strong>을 출력할 것이다. 즉, **[정치 카테고리 맞음, 경제 카테고리 아님, 사회 카테고리 맞음] **이렇게 분류되는 것이다.</p>
<p>이렇게 여러 개의 이진 꼬리표를 출력하는 분류 시스템이 바로 <strong>다중 레이블 분류 시스템</strong>이다.</p>
<h1 id="🔥-다중-레이블-분류를-할-수-있는-scikit-learn-함수">🔥 다중 레이블 분류를 할 수 있는 Scikit-learn 함수</h1>
<p>설계와 알고리즘 차이에 의해 기본적으로 모든 분류기가 다중 레이블 분류를 지원하지 않는다.</p>
<h3 id="1-kneighborsclassifier">1) <code>KNeighborsClassifier</code></h3>
<pre><code class="language-python">class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, *, 
weights=&#39;uniform&#39;, algorithm=&#39;auto&#39;, leaf_size=30, p=2, 
metric=&#39;minkowski&#39;, metric_params=None, n_jobs=None)[source]</code></pre>
<p><code>KNeighborsClassifier</code>는 K-최근접 이웃(K-NN) 알고리즘을 사용하여 샘플의 주변 이웃의 라벨을 보고, 가장 많은 라벨을 갖는 클래스를 할당한다. 
각 클래스에 대해 독립적인 판단을 내릴 수 있기에 다중 레이블 문제에서 유연하게 작동 가능하다고 한다.</p>
<pre><code class="language-python">from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# ...중략

# K-최근접 이웃 분류기 생성 (k=3)
knn = KNeighborsClassifier(n_neighbors=3)

# 학습
knn.fit(X_train, y_train)

# 예측
y_pred = knn.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print(f&quot;Accuracy: {accuracy}&quot;)</code></pre>
<p>참고 : <a href="https://scikit-learn.org/dev/modules/generated/sklearn.neighbors.KNeighborsClassifier.html">사이킷런 공식 문서</a></p>
<h3 id="2-onevsrestclassifier">2) <code>OneVsRestClassifier</code></h3>
<pre><code class="language-python">class sklearn.multiclass.OneVsRestClassifier(estimator, *, 
n_jobs=None, verbose=0)</code></pre>
<p><code>OneVsRestClassifier</code>는 본래 다중 클래스 분류 문제를 다중 이진 분류 문제로 변환하는 방법이다. 즉 이진 분류 문제로 나누어 학습하는 것이다. 각 레이블에 대한 이진 분류기를 학습시켜서 각 레이블에 대한 예측을 개별적으로 처리한다. 즉 직접 다중 레이블 분류를 지원하는 함수는 아니다.</p>
<pre><code class="language-python">from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.datasets import make_multilabel_classification
from sklearn.model_selection import train_test_split

# 다중 레이블 데이터를 생성
X, y = make_multilabel_classification(n_samples=100, n_classes=3, random_state=42)

# 데이터셋 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# SVM 분류기를 OneVsRestClassifier로 래핑하여 다중 레이블 분류 수행
clf = OneVsRestClassifier(SVC())
clf.fit(X_train, y_train)

# 테스트 데이터에 대한 예측
y_pred = clf.predict(X_test)</code></pre>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.multiclass.OneVsRestClassifier.html">사이킷런 공식 문서</a></p>
<h3 id="3-decisiontreeclassifier">3) <code>DecisionTreeClassifier</code></h3>
<pre><code class="language-python">class sklearn.tree.DecisionTreeClassifier(*, criterion=&#39;gini&#39;, 
splitter=&#39;best&#39;, max_depth=None, min_samples_split=2, 
min_samples_leaf=1, min_weight_fraction_leaf=0.0, 
max_features=None, random_state=None, max_leaf_nodes=None, 
min_impurity_decrease=0.0, class_weight=None, ccp_alpha=0.0, 
monotonic_cst=None)</code></pre>
<p><em>뭔 인자가 이렇게 괴랄하게 많지...</em></p>
<p>이 함수는 기본적으로 다중 레이블 분류를 지원한다.</p>
<p>결정 트리 모델이 각 레이블에 대해 독립적인 트리를 만들어서, 각 레이블에 대한 예측을 동시에 할 수 있다. 그래서 <strong>다중 출력 결정 트리</strong>라고 부른다.</p>
<p>참고로 별도의 추가적인 알고리즘 없이도 다중 레이블 출력이 가능하다.</p>
<pre><code class="language-python">from sklearn.tree import DecisionTreeClassifier

# 다중 레이블 분류용 데이터셋을 학습시키기 위한 결정 트리 분류기 생성
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)  # X_train: 입력 데이터, y_train: 다중 레이블 (2D 배열)

# 예측
y_pred = clf.predict(X_test)</code></pre>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html">사이킷런 공식 문서</a></p>
<h3 id="4-randomforestclassifier">4) <code>RandomForestClassifier</code></h3>
<pre><code class="language-python">class sklearn.ensemble.RandomForestClassifier(n_estimators=100, *,
criterion=&#39;gini&#39;, max_depth=None, min_samples_split=2, 
min_samples_leaf=1, min_weight_fraction_leaf=0.0, 
max_features=&#39;sqrt&#39;, max_leaf_nodes=None, 
min_impurity_decrease=0.0, bootstrap=True, oob_score=False, 
n_jobs=None, random_state=None, verbose=0, warm_start=False, 
class_weight=None, ccp_alpha=0.0, max_samples=None, 
monotonic_cst=None)</code></pre>
<p><em>이건 더 많네...</em></p>
<p>랜덤 포레스트는 여러 결정 트리의 앙상블을 통해 예측 성능을 향상시키며, 다중 레이블 문제에서도 동일한 방식으로 동작한다.</p>
<p>다중 레이블 분류 문제에서 랜덤 포레스트는 각 레이블에 대해 독립적인 트리를 생성하여 예측을 수행할 수 있다. 결정 트리처럼 다중 출력 지원이 가능하며, 기본적으로 다중 레이블 분류에 적합하게 동작한다.</p>
<pre><code class="language-python">from sklearn.ensemble import RandomForestClassifier

# 다중 레이블 분류용 랜덤 포레스트 분류기 생성
clf = RandomForestClassifier()
clf.fit(X_train, y_train)  # X_train: 입력 데이터, y_train: 다중 레이블 (2D 배열)

# 예측
y_pred = clf.predict(X_test)</code></pre>
<p>참고 : <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html">사이킷런 공식 문서</a></p>
<blockquote>
<p>주의! 다중 레이블 분류 데이터 형식</p>
</blockquote>
<p>위의 네 가지 함수들을 사용할 때, target label을 2차원 바이너리(0, 1) 배열 형식으로 준비해야 한다! 이 배열의 크기는 <code>(n_samples, n_labels)</code>로, 각 행은 하나의 샘플에 대해 여러 개의 레이블을 가질 수 있는지 여부를 나타낸다고 한다.</p>
<pre><code class="language-python">y_train = [
  [1, 0, 1],
  [0, 1, 0], 
  [1, 1, 0]
]</code></pre>
<h1 id="🔥-ovr-전략을-다중-레이블-분류에-사용">🔥 OvR 전략을 다중 레이블 분류에 사용</h1>
<blockquote>
<p>One-vs-the-rest (OvR) 다중 클래스 전략 = OvA 전략 이라고 한다.
cf) <a href="https://velog.io/@yoonie_03/ML-Multiclass-Classification#3-ova-ovo-%EC%84%A0%ED%83%9D-%EC%A0%84%EB%9E%B5">다중 클래스 OvA OvO 전략</a></p>
</blockquote>
<blockquote>
<p>작동 과정</p>
</blockquote>
<p>다중 레이블 문제에서 OvR을 사용할 때는 <strong>각 레이블에 대해 하나의 이진 분류기를 학습</strong>한다. 이 방식은 <code>Binary Relevance</code>라고도 불리며, 각 레이블을 독립적으로 분류한다.</p>
<ol>
<li><p>각 레이블을 이진 분류 문제로 변환</p>
</li>
<li><p><strong>각 레이블에 대해 독립적인 이진 분류기를 학습</strong></p>
<ul>
<li>분류기 1: 레이블 A vs 나머지 (A의 유무를 예측)</li>
<li>분류기 2: 레이블 B vs 나머지 (B의 유무를 예측)</li>
<li>분류기 3: 레이블 C vs 나머지 (C의 유무를 예측)</li>
</ul>
</li>
<li><p>예측 시, 각 레이블에 대해 독립적으로 예측을 수행</p>
<ul>
<li>결과적으로 각 샘플에 대해 레이블 A, B, C 중 어떤 것이 포함되어 있는지를 예측</li>
</ul>
</li>
</ol>
<h1 id="🔥-classifierchain">🔥 <code>ClassifierChain</code></h1>
<pre><code class="language-python">class sklearn.multioutput.ClassifierChain(base_estimator, *, 
order=None, cv=None, chain_method=&#39;predict&#39;, 
random_state=None, verbose=False)</code></pre>
<blockquote>
<p>OvR과는 작동 방식이 다르니 주의해 주어야 한다!</p>
</blockquote>
<p>다중 레이블 분류에서 레이블 간의 의존성을 고려하는 방식을 사용한다. 각 레이블을 순차적으로 예측하면서, <strong>이전에 예측한 레이블을 그 다음 레이블의 특징(feature)으로 사용한다</strong>는 것이 핵심이다 🔥 즉, 이전에 예측된 레이블들이 그 이후 레이블을 예측하는 데 영향을 미치게 된다!</p>
<h3 id="1-classifierchain-작동-방식">1) <code>ClassifierChain</code> 작동 방식</h3>
<p><strong>1. 순차적 예측</strong></p>
<ul>
<li>각 레이블에 대해 분류기를 하나씩 학습시키는데,
이때 각 분류기의 입력으로 원래 입력 데이터뿐만 아니라, </li>
<li><em>앞서 예측한 레이블도 포함*</em>시킨다.</li>
<li>앞서 관측한 것을 포함해야 하기에 순차적으로 관측하게 되는 것이다!</li>
</ul>
<p><strong>2. 순서 중요성</strong></p>
<ul>
<li>첫 번째 분류기는 원래 입력 데이터만 사용하지만, 두 번째 분류기부터는 이전 분류기의 예측 결과를 추가로 사용하여 학습합니다. 이렇게 학습된 각 분류기는 그 이후의 레이블 예측에 영향을 미치게 된다.</li>
</ul>
<h3 id="2-작동-방식-예시">2) 작동 방식 예시</h3>
<p>다음과 같은 3개의 레이블이 있다고 가정해 보자! (L1, L2, L3).</p>
<p>분류기 1: 입력 데이터 X를 사용하여 레이블 L1을 예측
분류기 2: 입력 데이터 X와 <strong>앞서 예측한 레이블 L1을 함께 사용하여 L2를 예측</strong>
분류기 3: <strong>입력 데이터 X, L1, L2를 모두 사용하여 L3을 예측</strong></p>
<p>이렇게 각 분류기의 예측은 이전 분류기의 예측 결과에 의존하게 되는 방식이다.</p>
<h2 id="정리">정리</h2>
<p><strong>OvR</strong> (기본적으로 다중 클래스 분류에 이용)</p>
<ul>
<li>각 레이블에 대해 독립적인 이진 분류기를 학습</li>
<li>레이블 간의 상관관계는 고려하지 않음</li>
<li>각 분류기는 서로 독립적</li>
</ul>
<p><strong>ClassifierChain</strong></p>
<ul>
<li>레이블 간의 상관관계를 반영</li>
<li>각 레이블의 예측 결과를 다음 레이블 예측에 활용</li>
<li>분류기가 순차적으로 연결된 방식으로 작동</li>
</ul>
<h1 id="🔥-평가-방식">🔥 평가 방식</h1>
<p>적절한 지표는 프로젝트에 따라 다르다.</p>
<p>1) $F_1$ 점수를 이용하는 방법
각 레이블의 $F_1$ 점수를 구하여 간단하게 평균 점수를 계산하는 방법이 잇따. </p>
<blockquote>
<p>만약 모든 레이블의 가중치가 같지 않다면,
레이블에 클래스에 지지도(support, target label에 속한 샘플 수)를 가중치로 주면 된다. <code>f1_score(average = &quot;weighted&quot;)</code>이렇게 설정하면 된다.</p>
</blockquote>
<p>2)<code>SVC</code>와 같이 기본적으로 다중 레이블 분류를 지원하지 않는 분류기 사용하는 경우</p>
<p>→ 레이블당 하나의 모델 학습</p>
<p>하지만 이 전략은 레이블 간의 의존성을 포착하기 어렵게 하기에 이 문제 해결을 위해 모델을 체인(chain)으로 구성하는 방법을 이용할 수 있다.</p>
<p>사이킷런에서 이런 작업을 수행하는 것이 위에서 다룬 <code>ClassifierChain</code> 클래스다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]2장 머신러닝 프로젝트 처음부터 끝까지]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning2%EC%9E%A5-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%B2%98%EC%9D%8C%EB%B6%80%ED%84%B0-%EB%81%9D%EA%B9%8C%EC%A7%80</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning2%EC%9E%A5-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%B2%98%EC%9D%8C%EB%B6%80%ED%84%B0-%EB%81%9D%EA%B9%8C%EC%A7%80</guid>
            <pubDate>Mon, 16 Sep 2024 22:58:29 GMT</pubDate>
            <description><![CDATA[<p><em>동아리에서 캐글을 직접 하면서 가장 먼저 들었던 의문은... &quot;대체 EDA가 뭐지?&quot; 라는 것이다. 제대로 된 순서도 모르고 다른 훌륭한 선두자들의 코드를 따라가면서 어영부영 따라갔었다... 순서가 좀 달라진 것 같지만 이제 드디어 제대로 된, 정석적인? 머신러닝 과정을 정리하고자 한다...할 수 있다~!</em></p>
<p>키보드 바꾸니까 할 맛난다 오예~</p>
<p>진행하는 주요 단계는 아래와 같다! 이걸 먼저 보고 했다면...너무 좋았을 것 같다 ㅠㅠ 핸즈온...왜 이제서야 나에게...</p>
<blockquote>
<ol>
<li>큰 그림을 본다</li>
<li>데이터를 구한다(load)</li>
<li>EDA (탐색 및 시각화)</li>
<li>머신러닝 알고리즘을 위해 데이터 준비</li>
<li>모델 선택 및 훈련</li>
<li>모데 미세 튜닝</li>
<li>솔루션 제시</li>
<li>시스템 launching, monitoring, 유지보수</li>
</ol>
</blockquote>
<h1 id="🔥21-실제-데이터로-작업하기">🔥2.1 실제 데이터로 작업하기</h1>
<p>책에서 여러 공개 데이터 저장소를 소개해주고 있다!
나중에 직접 연습할 때 쓰면 좋을 것 같다!</p>
<blockquote>
<p>유명한 공개 데이터 저장소</p>
</blockquote>
<ul>
<li><a href="https://openml.org">OpenML</a></li>
<li><a href="https://kaggle.com/datasets">Kaggle </a>(애증의 그곳)</li>
<li><a href="https://paperswithcode.com/datasets">PapersWithCode</a></li>
<li><a href="https://archive.ics.uci.edu/ml">UC 어바인 머신러닝 저장소</a></li>
<li><a href="https://registry.opendata.aws">아마존 AWS 데이터셋</a></li>
<li><a href="https://tensorflow.org/datasets">텐서플로 데이터셋</a></li>
</ul>
<blockquote>
<p>메타 포털 (공개 데이터 저장소가 나열되어 있는 다른 페이지)</p>
</blockquote>
<ul>
<li><a href="https://dataportals.org">데이터 포털</a></li>
<li><a href="https://opendatamornitor.eu">오픈 데이터 모니터</a></li>
<li><a href="http://lib.stat.cmu.edu/datasets/">StatLib 저장소</a>(Carnegie Mellon 통계학과에서 운영하는 공개 데이터셋 저장소)</li>
</ul>
<blockquote>
<p>인기 있는 공개 데이터 저장소가 나열되어 있는 다른 페이지</p>
</blockquote>
<ul>
<li><a href="https://homl.info/9">위키백과 머신러닝 데이터셋 목록</a></li>
<li><a href="https://homl.info/10">Quora</a></li>
<li><a href="https://www.reddit.com/r/datasets">데이터셋 서브레딧</a>(역시...reddit😮)</li>
</ul>
<p>책에서는 StatLib 저장소에 있는 <a href="https://goo.gl/QgRbUL">California Housing Prices</a> 데이터를 사용했다! 교육 목적으로 사용하기 위해 범주형 특성을 추가하고 몇 가지는 제외했다고 한다.</p>
<h1 id="🔥22-큰-그림-보기">🔥2.2 큰 그림 보기</h1>
<p>가장 궁금했던 제목이다. 앞으로도 머신러닝 관련 프로젝트 할 때도 가장 중요하게 볼 부분이 아닐까 조심스레 예측해본다!</p>
<h3 id="221-문제-정의">2.2.1 문제 정의</h3>
<blockquote>
<p>목적이 무엇인지 정확히 보기...!</p>
</blockquote>
<p>모델을 만드는 것이 아니라 이 <strong>모델을 통해 얻을 수 있는 무언가</strong>가 있을 것이다! 이렇게 목적을 아는 것은 문제를 어떻게 구성할지, 어떤 알고리즘을 선택하고 모델 성능 평가를 어떻게 할지, 튜닝을 위해 얼마 만큼의 노력을 투여할 지 결정하기에 아주 중요한 역할을 한다! </p>
<p><strong>목적을 설정하는 것</strong>은 언제나 중요한 핵심인 것 같다. 결국 목적이 있어야, 무엇이든 할 일이 정해진다!</p>
<p>머신러닝에 주입하는 정보를 <strong>신호(signal)</strong>이라고 한다. Claude Shannon의 정보 이론에 따라 종종 &#39;신호&#39;라고 부른다. 이론에 따르면 신호/잡음 비율이 높은 것이 좋다. (결국 잡음은 적어야 한다는 뜻!)</p>
<blockquote>
<p>** pipeline(파이프라인)**</p>
</blockquote>
<p>데이터 컴포넌트(component)들이 연속되어 있는 것을 데이터 파이프라인(pipeline)이라고 한다. 머신러닝 시스템은 파이프라인을 사용하는 일이 매우 흔하다. 보통 비동기적으로 작동하며, 독립적이다.</p>
<p>각 컴포넌트는 많은 데이터를 추출해 처리해서 그 결과를 다른 데이터 저장소로 보낸다. 따라서 컴포넌트 사이의 인터페이스는 데이터 저장소뿐이다.</p>
<hr>
<p>캘리포니아 주택 문제의 경우, labeled된 훈련 샘플이 잇으니 지도 학습이며, 예측에 사용할 특성이 여러 개이니 <strong>다중 회귀(multiple regression)</strong>문제, 각 구역마다 하나의 값을 예측하니 <strong>단변량 회귀(univariate regression)</strong> 문제이다! 또한 데이터가 메모리에 들어갈 만큼 작기에 배치 학습이 적절하다. 데이터가 너무 크면 <strong>맵리듀스(MapReduce) 기술</strong>을 이용하면 된다!</p>
<h3 id="222-성능-측정-지표-선택">2.2.2 성능 측정 지표 선택</h3>
<p>회귀 문제는 보통 <strong>평균 제곱근 오차</strong>(<strong>R</strong>oot <strong>M</strong>ean <strong>S</strong>quare <strong>E</strong>rror)를 사용한다.</p>
<p>$$
 \mathrm{RMSE},(\mathbf{X}, h) = \sqrt{\frac{1}{m}\sum_{i=1}^{m}(h(\mathbf{x})^{(i)}-y^{(i)})^2}
$$</p>
<p>이상치로 보이는 구역이 많다면<br><strong>평균 절대 오차</strong>(<strong>M</strong>ean <strong>A</strong>bsolute <strong>E</strong>rror) = <strong>평균 절대 편차</strong>(<strong>M</strong>ean <strong>A</strong>bsolute <strong>D</strong>eviation)를 고려하기도 한다! </p>
<p>$$
 \mathrm{MAE},(\mathbf{X}, h) = \frac{1}{m}\sum_{i=1}^{m}\left|(h(\mathbf{x})^{(i)}-y^{(i)})^2 \right|
$$</p>
<p>RMSE와 MAE 모두 예측값의 벡터와 타깃값의 벡터 사이의 거리를 재는 방법이다. 거리 측정엔 에는 여러 가지 norm을 사용할 수 있다!</p>
<h3 id="223-가정-검사">2.2.3 가정 검사</h3>
<p>이 부분은 qa 관련 분야 같다. 여러 가정을 나열하고 검사하는 과정이다. prompt engineering 분야로 보인다.</p>
<h1 id="🔥23-데이터-가져오기">🔥2.3 데이터 가져오기</h1>
<p>새로운 캐글 주제 시작하면 어김없이 했던 일을 하고 있다.
<code>df=pd.read_csv(&quot;path&quot;)</code> 정말 열심히 사용했던 함수다
<code>df.head()</code> 이것도 단골 함수였다.</p>
<p><code>df.describe()</code>, <code>value_counts()</code> 등의 다양한 method가 나왔다.</p>
<p>테스트 세트로 훈련한 모델을 테스트 세트를 이용하여 일반화 오차를 추정하면 과대적합이 일어나면서 확실히 <strong>일반화된</strong> 모델을 얻을 수 없고, 기대한 성능을 얻을 수 없을 것이다!</p>
<p>이런 현상을 <strong>데이터 스누핑(data snooping)</strong> 편향이라고 한다!</p>
<h1 id="🔥24-데이터-이해를-위한-탐색과-시각화">🔥2.4 데이터 이해를 위한 탐색과 시각화</h1>
<p>여러 Tip이 있길래 유용한 정보 위주로 정리했다!</p>
<ul>
<li><p>지리적 데이터 시각화
→ 산점도 이용! 투명도 조정하는 <code>alpha</code> 옵션을 이용해서 밀집도 파악 더 용이하게 할 수 있음! 여기서는 cmap으로 <code>jet</code>를 썼는데, 무지개색으로 기억하면 될 것 같다. 비즈니스 용으로 딱인 듯하다.</p>
</li>
<li><p>상관관계 조사하기
→ 데이터셋의 크기가 크면 사용하지 못 하는 것 같다. <strong>표준 상관계수(standard correlation coefficient, Pearson의 $r$ 이라고도 불림)</strong>는 <code>corr()</code> 메서드를 이용해 계산할 수 있다.</p>
<ul>
<li><p>상관계수는 -1부터 1까지의 범위를 가지며, 1에 가까우면 강한 양의 상관관계를 가진다는 뜻이다. 1에 가까우면 비례 관계를, -1에 가까우면 반비례 관계를 가진다. 0에 가까우면 선형적인, 즉 상관관계가 없다.</p>
</li>
<li><p>Tip❗판다스의 <code>scatter_matrix</code>를 이용해 숫자형 특성 간 산점도를 그리면 상관 관계를 살필 수 있다!❗</p>
</li>
<li><p>상관 계수는 선형적인 상관관계만 측정하기에 비선형적인 관계는 잡을 수 없기에 주의해야 한다! 비선형으로 보일지라도 사실은 의미가 있는 것일 수도 있다는 것!</p>
</li>
</ul>
</li>
<li><p>특성 조합으로 실험하기
→  여러 가지 조합을 만들어서 상관관계를 확인한다. 컬럼 몇 가지를 조합해서 새로운 값을 만드는 과정으로 생각하면 좋을 것 같다!</p>
</li>
</ul>
<h1 id="🔥25-머신러닝-알고리즘을-위한-데이터-준비">🔥2.5 머신러닝 알고리즘을 위한 데이터 준비</h1>
<p>이 작업은 자동화해야 한다고 한다!</p>
<p>자동화를 해두면
✅ 데이터 변환 손쉽게 가능
✅ 프로젝트에 재사용 가능한 변환 라이브러리 점진적 구축 가능
✅ 실제 시스템에서 새 데이터 주입 전에 함수를 사용해 변환 가능
✅ 데이터 변환 쉽게 시도 가능 + 베스트 조합 찾기 가능
이렇게 다양한 장점들이 있다!</p>
<h3 id="251-데이터-정제">2.5.1 데이터 정제</h3>
<p>항상 데이터에 존재하는 <code>Nan</code>값, 결측값을 처리하는 경우다.</p>
<p>해당 행 또는 열을 지우거나
<strong>누락된 값을 채우면 된다</strong> 대체(imputation)라고 한다!
<code>dropna()</code>, <code>drop()</code>, <code>fillna()</code> 메서드를 주로 활용한다.</p>
<p>사이킷런에 <code>SimpoleImputer</code> 클래스를 이용하면 좋다! 이 클래서는 각 특성의 중간값을 저장하기에 유용하다. 나중에 시스템이 서비스될 때 새로운 데이터에서 어떤 값이 누락될지 확신할 수 없기에 모든 수치형 특성에 imputer를 적용하는 것이 좋다.</p>
<p>👉 <a href="https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html">공식문서</a></p>
<h3 id="252-텍스트와-범주형-특성-다루기">2.5.2 텍스트와 범주형 특성 다루기</h3>
<p><code>OrdinalEncoder</code> : 카테고리를 텍스트에서 숫자로 변환해주는 메서드
❗ 이 방식의 큰 문제점은 인접한 두 값이 비슷하다고 생각한다는 점이다. </p>
<p><code>OneHotEncoder</code> : 카테고리별 이진 특성을 만들어 해결하는 <strong>원-핫 인코딩 *<em>방식, 새로운 특성을 *</em>더미(dummy) 특성</strong>이라고 부르기도 한다!</p>
<blockquote>
<p>사이킷런에서 <code>OneHotEncoder</code> 출력은 <strong>사이파이 희소 행렬</strong> 이다</p>
</blockquote>
<p>희소 행렬 자체는 내부적으로 0이 아닌 값과 그 위치만 저장하기에 메모리 절약과 계산 속도에서 장점을 가진다. 보통 2D배열처럼 사용할 수있지만, 넘파이 배열로 바꾸려면 <code>toarray()</code> 메서드 호출이 필요하다</p>
<p>아니면 <code>sparse_output=False</code> 설정을 통해 일반적인 넘파이 배열을 반환하도록 할 수 있다!</p>
<p><code>categories_</code> : 인스턴스 변수를 사용해 카테고리 리스트 얻기 가능
<code>get_dummies</code> : 판다스에서 범주형 특성을 원-핫 표현으로 바꾸어줌</p>
<blockquote>
<p><code>OneHotEncoder</code>는 <code>get_dummies</code>와 달리 알 수 없는 카테고리를 감지하고 예외를 발생시킨다. <code>handdle_unknown = ignore</code> 설정을 해두면 알 수 없는 카테고리를 그냥 0으로 나타낼 수 있다!</p>
</blockquote>
<h3 id="253-특성-스케일링-변환">2.5.3 특성 스케일링 변환</h3>
<p>feature scaling
틈만나면 kaggle에서 자주 보이던 정규화가 생각난다.</p>
<p>모든 특성의 범위를 같게 만들어주는 방법
: <strong>min-max 스케일링</strong>, <strong>표준화(standardization)</strong></p>
<p><strong>min-max 스케일링</strong>(=정규화 normalization)
각 특성에 대해서 0~1 범위에 들도록 값을이동, 스케일 조절</p>
<p><code>MinMaxScaler</code> 에서 <code>feature_range = (-1, 1)</code>를 통해
범위 조정이 가능하다. 보통 신경망에서는 평균이 0인 -1~1 사이 범위가 선호된다고 한다!</p>
<p><strong>표준화(standardization)</strong> : 항상 평균이 0
(값 - 평균) / 표준편차</p>
<p>특정 범위로 값을 제한하지 않기에 이상치에 영향을 덜 받는다
(정규화는 특정 범위로 줄여버리기에 이상치도 함께 줄여지는 꼴이다)</p>
<p><code>StandardScalar</code>가 사이킷런에서 제공되고 있다.</p>
<p><strong>멱법칙 분포(power law distribution)</strong>
특성 분포의 꼬리가 아주 길고 두껍다면 특성을 로그값으로 바꿔준다.
*보통 population 특성이 대략적으로 멱법칙을 따른다고 한다.
*오른쪽 꼬리가 두꺼운 양수 특성의 경우 특성을 제곱근으로 바꾸어 사용</p>
<p><strong>버킷타이징(bucketizing)</strong>
분포를 거의 동일한 크기로 자르고, 해당하는 버킷의 인덱스로 바꾸기
ex) 각 값을 백분위로 바꾸기
거의 동일한 크기의 버킷을 사용하면 거의 균등 분포인 특성을 만들 수 있기에 추가적인 스케일링이 필요가 없다. 또한 버킷 개수로 나누어 0~1 범위를 만들수도 있다.</p>
<p><strong>멀티모달 분포(multimodal distribution)</strong>
모드(mode)라 불리는 정점이 두 개 이상 나타나는 분포
→ 버킷타이징을 이용하면 도움이 된다.</p>
<p>→ 주요 모드에 대해 특정 모드 사이의 유사도를 나타내는 특성 추가</p>
<ul>
<li><strong>방사 기저 함수(</strong>R<strong>adial **B</strong>asis <strong>F</strong>unction) 사용</li>
<li>가우스 RBF가 가장 널리 사용(입력값이 고정 포인트에서 멀어질수록 출력값이 지수적으로 감소), 하이퍼파라미터 감마는 유사도 값이 감소하는 빠르기를 결정</li>
</ul>
<p><code>inverse_transform()</code>
역변환을 수행하는 함수, 스케일링 해둔 것을 돌려놓는 역할</p>
<h3 id="254-사용자-정의-변환기">2.5.4 사용자 정의 변환기</h3>
<p>사용자 정의 변환, 정제 연산, 특성 결합을 위해 작성할 필요가 있음.</p>
<p>사이킷런은 <strong>덕 타이핑(duck typing)</strong>에 의존하기에 어떤 클래스가 특정 클래스를 상속할 필요가 없다.</p>
<h3 id="255-변환-파이프라인">2.5.5 변환 파이프라인</h3>
<p>사이킷런은 변환을 순서대로 처리하도록 도와주는 <a href="https://scikit-learn.org/stable/api/sklearn.pipeline.html">Pipeline</a> 클래스를 제공한다.</p>
<ul>
<li>생성자 : 연속적인 단계를 정의하는 이름/추정기 쌍(2개의 원소 가진 tuple)의 리스트 받음.</li>
<li>이름은 (__) 이걸 포함하지 않으면서 고유하다면 어던 것도 가능</li>
<li>(__)은 하이퍼파라미터 튜닝에 사용</li>
<li>추정기는 마지막을 제외하고 모두 변환기여야 함. 변환기, 예측기부터 다른 타입의 추정기까지 무엇이든 가능</li>
</ul>
<h1 id="🔥26-모델-선택과-훈련">🔥2.6 모델 선택과 훈련</h1>
<p><strong>- 훈련 세트에서 평가</strong></p>
<p>사이킷런의 <code>mean_squared_error()</code>함수에서 <code>squared = False</code>로 지정하여 RMSE를 계산할 수 있다!</p>
<p>다만, 훈련세트에서만 평가하면 안 된다. 일반화를 위해 훈련에 사용하지 않은 데이터를 이용해야 한다!</p>
<p><strong>- 교차 검증으로 평가</strong></p>
<p><code>train_test_split</code> 함수를 이용할 수도 있지만,
<a href="https://velog.io/@yoonie_03/ML-K-fold-vs-StratifiedKFold">k-폴드 교차 검증</a> 기능 등을 사용할 수 있다.</p>
<blockquote>
<p>사이킷런의 교차 검증 기능은 scoring 매개변수에 (낮을수록 좋은) 비용 함수가 아니라 (클수록 좋은) 효용 함수를 기대한다! 그래서 RMSE의 음숫값을 출력한다.</p>
</blockquote>
<p>훈련 오차가 작고 검증 오차가 높으면 과대적합이라 볼 수 있다.</p>
<h1 id="🔥27-모델-미세-튜닝">🔥2.7 모델 미세 튜닝</h1>
<ul>
<li><p><strong>그리드 서치 (GridSearchCV)</strong></p>
<ul>
<li>탐색하고자 하는 하이퍼파라미터와 시도해볼 값 지정</li>
<li><code>grid_search.best_estimator_</code> 속성으로 최상의 추정기 얻기 가능</li>
</ul>
</li>
<li><p><strong>랜덤 서치 (RandomizedSearchCV)</strong></p>
<ul>
<li>각 반복마다 하이퍼파라미터에 임의의 수를 대입하여 지정한 횟수만큼 평가</li>
<li>하이퍼파라미터 값이 연속적, 또는 값이 많은데 이산적이라면 랜덤 서치는 1000번 실행하면 하이퍼파라미터마다 1000개의 다른 값 탐색</li>
<li>그리드 서치와 달리 10개의 값을 넣는다면, 그리드 서치는 훈련이 10배 더 걸리지만, 랜덤 서치는 탐색 시간이 늘어나지 않는다!</li>
<li>지정한 반복 횟수만큼 실행 가능</li>
</ul>
</li>
<li><p><code>Scikit Learn과 그리드 서치, 랜덤 서치</code></p>
<ul>
<li><code>HalvingRandomSearchCV</code>와 <code>HalvingGridSearchCV</code> 제공</li>
<li>작동 방식<ul>
<li>1) 반복에서 많은 하이퍼파라미터 조합(후보)이 그리드 서치나 랜덤 서치를 통해 생성, 후보들로 교차 검증을 사용해 평가<ul>
<li>반복 속도를 높이기 위해 훈련 세트의 작은 일부분에서 훈련되게 하기, 반복 횟수 줄이기 등</li>
</ul>
</li>
<li>2) 몇 번의 반복이 진행된 후 최종 후보들이 전체 자원을 사용해 평가</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>*<em>- 앙상블(ensemble) 방법 *</em></p>
<ul>
<li>최상의 모델을 연결하는 방법이다</li>
<li>여러 방법에서 얻은 예측의 평균을 이용하여 예측하는 방법도 있다!</li>
</ul>
<p><strong>- 최상의 모델과 오차 분석</strong></p>
<ul>
<li><code>randomforestRegressor</code>는 정확한 예측을 만들기 위해 각 특성의 상대적인 중요도를 알려준다
<code>sklearn.feature_selection.SelectFromModel</code> 변환기는 자동으로 가장 덜 유용한 특성을 제거해 준다. <code>feature_importances</code> 속성을 확인하여 가장 유요한 특성을 선택한다!</li>
</ul>
<p><strong>- 테스트 세트로 시스템 평가</strong></p>
<ul>
<li>어떤 경우는 오차의 점 추정(point estimate)으로 충분하지 않다</li>
<li><code>scipy.stats.t.interval()</code>을 사용해 일반화 오차의 95% <strong>신뢰 구간(confidence interval)</strong> 설정 가능</li>
<li>하이퍼파라미터 튜닝을 많이 했다면 교차 검증을 사용해 측정한 것보다 성능이 조금 낮은 것이 보통이다. (튜닝 자체가 검증 셋에서 잘 작동하도록 맞춰둔 것이기에 그럴 수밖에 없다)</li>
</ul>
<h1 id="🔥28-론칭-모니터링-시스템-유지-보수">🔥2.8 론칭, 모니터링, 시스템 유지 보수</h1>
<p><code>joblib</code> 라이브러리를 이용하면  모델 저장이 가능하다!</p>
<pre><code class="language-python">import joblib

joblib.dump(final model, &quot;my_model.pkl&quot;</code></pre>
<p>피클 형태로 저장해주는 것 같다.</p>
<p>모델은 불러올 함수, 클래스 다 불러오고 아래와 같이 load 한다.</p>
<pre><code class="language-python">final_model_reloaded = joblib.load(&quot;my_model.pkl&quot;)

new data = [...] # 예측을 새로 만드는 구역
predictions = final_model_reloaded.predict(new_data)</code></pre>
<p>서버가 시작될 때 모델을 로드하는 것이 좋으며, REST API를 통해 모델을 올릴 수도 있다. (이 내용을 1학년 때 봐야 했는데...!!!!)</p>
<p>REST API를 사용하면 주 애플리케이션을 건드리지 안고 모델 업그레이드가 용이하며, load balancing할 수 있기에 규모 확장도 쉽다! 또한 웹 애플리케이션을 python이 아닌 다른 언어를 사용하는 것도 가능하다.</p>
<p>Google의 Vertex AI (구 구글 클라우드 AI, ML 엔진)같은 클라우드에 배포하는 방법도 있다.</p>
<blockquote>
<p>배포에서 끝나는 줄 알 았는데 모니터링 코드 작성도 해야한다!</p>
</blockquote>
<ol>
<li>정기적으로 새로운 데이터를 수집하고 label 달기</li>
<li>모델을 훈련하고 hyperparameter를 자동으로 미세 튜닝하는 코드 작성, 작업에 따라 매일 또는 매주 자동으로 실행</li>
<li>업데이트된 test set에서 이전 모델을 평가하는 코드 작성, 성능이 감소하지 않았을 때만 모델이 배포되도록 조절! (테스트 세트의 여러 subset에서 성능 테스트할 수 있도록 하기!)</li>
</ol>
<p><strong>모델의 입력도 모니터링 해주어야 한다!</strong>
ex) 잘못 감지된 신호
모델의 성능이 실제로 감소하기까지 시간이 걸릴 수 있으니, 사전에 input 과정에서 잡아낸다!</p>
<p><strong>마지막으로 중요한 것! 백업이다.</strong>
이전 모델로 언제든 roll back 할 수 있도록 준비해야 한다. 또한 이 과정이 되어 있으면 새로운 모델을 이전 모델과 비교하는 것도 가능하다.</p>
<h1 id="🔥29-직접-해보기">🔥2.9 직접 해보기</h1>
<p>kaggle 열심히 하자...! 고수준 알고리즘을 탐색하느라 전체 프로세스 구축을 못 하는 것보다는 서너 개의 알고리즘을 이용해서 전체 프로세스를 올바르게 구축하는 것이 좋다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] 머신러닝 시스템의 종류]]></title>
            <link>https://velog.io/@yoonie_03/ML-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%A2%85%EB%A5%98</link>
            <guid>https://velog.io/@yoonie_03/ML-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%A2%85%EB%A5%98</guid>
            <pubDate>Mon, 09 Sep 2024 18:34:13 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>[Hands-On-Machine Learning]에서 머신러닝 시스템을 분류하는 기준에 대해 다루었었다. 특별히 따로 글을 작성해서 제대로 정리하려고 한다.</p>
</blockquote>
<p> 종류가 많으면 항상 분류하는 <strong>기준</strong>이 존재한다. </p>
<ul>
<li>1.4.1 ) 훈련 지도 방식 (학습하는 동안의 지도 형태나 정보량에 따라 분류)<ul>
<li>지도 학습(supervised learning)</li>
<li>비지도 학습(unsupervised learning)</li>
<li>번외) 준지도 학습(semi-supervised learning)</li>
<li>자기 지도 학습(self-supervised learning)</li>
<li>강화 학습(reinforcement learning)</li>
</ul>
</li>
<li>1.4.2 ) 실시간으로 점진적인 학습을 하는지 아닌지<ul>
<li>온라인 학습</li>
<li>배치 학습</li>
</ul>
</li>
<li>1.4.3 ) 예측 방식에 따른 차이<ul>
<li>사례 기반 학습(알고 있는 데이터 포인트와 새 데이터 포인트 비교)</li>
<li>모델 기반 학습(훈련 데이터셋에서 패턴 발견하여 예측 모델 구축)</li>
</ul>
</li>
</ul>
<h1 id="훈련-지도-방식">훈련 지도 방식</h1>
<blockquote>
<p>학습하는 동안의 지도 형태나 정보량에 따라 분류
 지도 학습, 비지도 학습, 준지도 학습, 자기 지도 학습, 강화 학습</p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="left">방식</th>
<th align="left">활용예시</th>
</tr>
</thead>
<tbody><tr>
<td align="center">지도 학습</td>
<td align="left">알고리즘에 주입하는 훈련 데이터에 label이라는 원하는 답이 포함됨</td>
<td align="left">분류, 회귀</td>
</tr>
<tr>
<td align="center">비지도 학습</td>
<td align="left">훈련 데이터에 레이블이 없음, 스스로가 연결고리를 찾음</td>
<td align="left">계층 군집, 시각화 알고리즘, 차원 축소, t-SNE 시각화, 이상치 탐지, 특이치 탐지, 연관 규칙 학습</td>
</tr>
<tr>
<td align="center">준지도 학습</td>
<td align="left">레이블이 일부만 있는 데이터를 다룸, 지도 학습과 준지도 학습의 조합으로 이루어짐</td>
<td align="left">구글 포토 서비스</td>
</tr>
<tr>
<td align="center">자기 지도 학습</td>
<td align="left">레이블이 전혀 없는 데이터셋에서 &quot;레이블이 완전히 부여된 데이터셋을 생성하는 것&quot;,</td>
<td align="left">손상된 이미지 복원, 사진에서 원치 않는 물제 삭제</td>
</tr>
<tr>
<td align="center">강화 학습</td>
<td align="left">환경을 관찰해서 보상과 벌점을 받으며, 최상의 전략을 스스로 학습</td>
<td align="left">오프라인학습, 알파고</td>
</tr>
</tbody></table>
<blockquote>
<h3 id="이상치-탐지-vs-특이치-탐지"><strong>이상치 탐지</strong> vs <strong>특이치 탐지</strong></h3>
</blockquote>
<p>이상치 탐지의 예 : 신용카드 부정거래 감지, 제조 결함 잡아내기, 학습 알고리즘에 주입하기 전에 데이터셋에서 이상한 값을 자동으로 제거</p>
<p>이상치 탐지의 방식 : 훈련하는 동안 대부분 정상 샘플 만나며, 새로운 샘플 봤을 때 정상인지 이상치인지 판단</p>
<p>특이치 탐지 : 훈련 세트에 있는 모든 샘플과 달라 보이는 새로운 샘플 탐지가 목적, 따라서 <strong>알고리즘으로 감지하고 싶은 샘플을 모두 제거한 후 매우 깨끗한 훈련 세트</strong>가 필요함.</p>
<p>ex) 1% 치와와 + 다른 강아지 99%</p>
<p>이상치 : 치와와가 매우 드물고 다른 강아지와 다르니까 이상치!</p>
<p>특이치 : 새로운 치와와 사진을 특이치로 처리 X</p>
<h1 id="배치-학습과-온라인-학습">배치 학습과 온라인 학습</h1>
<blockquote>
<p>입력 데이터의 스트림(stream)으로부터 점진적으로 학습할 수 있는지 여부</p>
</blockquote>
<h3 id="배치-학습batch-learning">배치 학습(batch learning)</h3>
<p>점진적 학습 불가, 가용한 데이터 모두 사용해서 훈련
시간과 자원을 많이 소모하기에 오프라인에서 수행 <strong>&lt;오프라인 학습(offline learning)&gt;</strong></p>
<p>당연히 세상은 빠르게 변하기에 과거의 데이터로 학습된 모델의 성능은 시간이 지남에 따라 천천히 감소하는 경향이 있다.</p>
<p>이를 모델 부패(model rot) 또는 데이터 드리프트(data drift)라고 한다.</p>
<p>결국 오래된 데이터를 사용해서 훈련한 모델의 문제점을 고치려면, 최신 데이터에서 모델을 정기적으로 재훈련 해줄 수밖에 없다! 모델 훈련 주기는 상황에 따라 달라진다.</p>
<p>데이터 훈련 시간, 주어진 컴퓨팅 자원 등을 고려하여 잘 학습해야 하는데, 
위와 같은 한계에 부딪힌다면 점진적으로 학습할 수 있는 알고리즘을 사용하는 것이 훨씬 낫다.</p>
<h3 id="온라인-학습online-learning">온라인 학습(online learning)</h3>
<blockquote>
<p>온라인 학습이라는 용어보다는 점진적 학습이란 용어를 핸즈온에서는 권장했다. 확실히 온라인이라는 용어는 오해할 소지가 크다고 느껴서 온라인 학습보다는 <strong>점진적 학습(incremental learning)</strong>이란 단어로 이해하려고 했다.</p>
</blockquote>
<p>온라인 학습에서는 데이터를 순차적으로 한 개씩 또는 <strong>미니배치(mini-batch)</strong>라 부르는 작은 묶음 단위를 주입하여 시스템을 훈련시키는데, 확실히 한 번에 학습하는 양이 줄어서 매 학습 단계가 빠르고 비용이 적게 든다. 그래서 데이터가 도착하는 대로 즉시 학습이 가능하다고 한다. 그래서 주식 시장 같은 금융권 쪽에 더 유리하다고 하는 것 같다. 또한 컴퓨팅 자원이 매우 한정된 모바일 디바이스에서 모델 훈련 시 유리하다고 한다.</p>
<blockquote>
<p>또한 매우 큰 데이터셋에서 모델을 훈련할 수도 있다고 한다. 이를 <strong>외부 메모리 학습(out-of-core learning)</strong>이라고 한다.</p>
</blockquote>
<p>온라인 학습 시스템에서중요한 파라미터는 
변화하는 데이터를 얼마나 빠르게 적응할 것인지 보는 <code>학습률(learning rate)</code>이다.</p>
<p>학습률을 높게 설정하면 최신의 것을 반영하기에 더 좋을 것 같아 보이지만, 그만큼 예전 데이터를 금방 잊어버리게 될 것이기에 좋진 않다.(욕 대신 사용하는 초성만 밴 되는 경우를 생각했다. 이 초성만 밴 된다면, 오리지널 욕이 그대로 사용될 것이다.)</p>
<p>반대로 학습률이 너무 낮으면 시스템의 관성이 더 커져서 더 느리게 학습된다고 한다. </p>
<blockquote>
<p>그럼 어떻게?</p>
</blockquote>
<p>온라인 학습에서 가장 큰 문제점은 시스템에 <strong>나쁜 데이터</strong>가 주입되면 급격히 성능이 떨어지는 것이라 한다. 이런 위험성을 줄이기 위해 시스템을 평소에 잘 들여다보면서 나쁜 데이터가 학습되지 않도록 주의해야 한다. 또한 입력 데이터를 모니터링(이상치 탐지 알고리즘 등)해서 비정상 데이터를 잡도록 해야한다.</p>
<h1 id="배치-학습과-온라인-학습-1">배치 학습과 온라인 학습</h1>
<blockquote>
<p>어떻게 <strong>일반화(generalization)</strong>되는가?</p>
</blockquote>
<p> 머신러닝의 작업은 <strong>예측</strong>을 만드는 것!</p>
<p> 이 예측이 곧 일반화의 의미라 보면 좋을 것 같다.</p>
<p> 훈련 데이터에서도 물론! 높은 성능을 내어야 하지만, <strong>진짜 목표는 새로운 샘플에 잘 작동하는 모델을 만드는 것</strong>이다.</p>
<h3 id="사례-기반-학습">사례 기반 학습</h3>
<blockquote>
<p>단순히 기억하는 것</p>
</blockquote>
<p> 예시 ) 스팸 메일과 유사한 메일을 구분하도록 스팸 필터 프로그래밍</p>
<p> 이 경우 두 메일 사이의 유사도(similarity)를 측정해야 한다.
 (보통 매우 간단한 유사도 측정 시엔 공통으로 포함된 단어를 세는 경우가 있다)</p>
<h3 id="모델-기반-학습">모델 기반 학습</h3>
<blockquote>
<p>샘플들의 모델을 만들어 예측에 사용하는 것</p>
</blockquote>
<p>데이터가 흩어져 있지만(=무작위성이 있지만)
어떤 모델을 선택하고, 그 모델의 파라미터를 조절해서 
결국 그 모델이 최상의 성능을 내도록 하는 값을 알아낼 수 있다.
이때 최적의 파라미터의 최적값을 찾는 과정을 모델을 <code>훈련(training)</code>이라고 한다.</p>
<p>이때 모델의 성능을 나타내는 지표로는 여러 가지가 있다.</p>
<p>모델이 얼마나 좋은 지 측정 : <code>효용 함수(utility) = 적합도 함수(fitness function)</code>
모델이 얼마나 나쁜 지 측정 : <code>비용 함수(cost function)</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Hands-On-Machine Learning]1장 한 눈에 보는 머신러닝]]></title>
            <link>https://velog.io/@yoonie_03/Hands-On-Machine-Learning1%EC%9E%A5-%ED%95%9C-%EB%88%88%EC%97%90-%EB%B3%B4%EB%8A%94-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D</link>
            <guid>https://velog.io/@yoonie_03/Hands-On-Machine-Learning1%EC%9E%A5-%ED%95%9C-%EB%88%88%EC%97%90-%EB%B3%B4%EB%8A%94-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D</guid>
            <pubDate>Mon, 09 Sep 2024 17:58:32 GMT</pubDate>
            <description><![CDATA[<p>머신러닝 입문서로 불리는 핸즈온 머신러닝을 이해한 대로 정리해보려고 한다.</p>
<h1 id="11-🔥머신러닝이란">1.1 🔥머신러닝이란?</h1>
<p>머신러닝의 공학적인 정의는 아래와 같다</p>
<blockquote>
<p>A computer program is said to learn from experience E with respect to some task T and some performance measure P, if its performance on T, as measured by P, improves with experience E.
Tom Mitchell, 1997</p>
</blockquote>
<p><strong>훈련 세트(training set)</strong> : 시스템이 학습하는 데 사용하는 샘플
<strong>훈련 사례(training instance)</strong> or 샘플(sample) : 각각의 훈련 데이터
<strong>모델(model)</strong> : 머신러닝 시스템에서 학습하고 예측을 만드는 부분
*<em>정확도(accuracy) *</em>: 머신러닝의 공학적인 정의에서 언급한 성능 측정 P</p>
<p><em>모델 예시 : 신경망(neural network), 랜덤 포레스트(random forest)</em></p>
<h1 id="12-🔥머신러닝을-사용하는-이유">1.2 🔥머신러닝을 사용하는 이유</h1>
<ul>
<li><p>기존 솔루션으로 는 많은 수동 조정과 규칙이 필요한 문제에 유용
: 머신러닝 모델이 코드를 간단하게 만들고 전통적인 방법보다 더 잘 수행 가능
: 문제가 어려워지면 더욱 규칙이 길고 복잡해지므로 <strong>유지 보수에 용이하지 않음.</strong></p>
</li>
<li><p>전통적인 방식으로는 해결 방법이 없는 복잡한 문제
: 가장 뛰어난 머신러닝 기법으로 해결 방법 찾기 가능
: <strong>음성 인식(speech recognition)</strong>이 그 예시다</p>
</li>
<li><p>유동적인 환경
: 머신러닝 시스템은 새로운 데이터로 쉽게 재훈련이 가능해서 최신 상태를 유지하는 것이 가능하다 (기존의 상황이었다면 수동으로 하나하나 고쳐주어야 함!)</p>
</li>
<li><p>복잡한 문제와 대량의 데이터에서 insight 얻기
: <strong>데이터 마이닝(data mining)</strong> : 대용량의 데이터를 분석하여 숨겨진 패턴을 발견하는 것, 머신러닝을 잘 활용할 수 있는 분야
: 머신러닝을 통해 예상치 못한 <strong>상관관계</strong>나 <strong>새로운 추세</strong> 발견해서 문제 이해 가능</p>
</li>
</ul>
<h1 id="13-🔥적용-사례">1.3 🔥적용 사례</h1>
<blockquote>
<p>흥미로워 보이는 사례 위주로 정리했다</p>
</blockquote>
<ul>
<li><p>여러 가지 성과 자료를 바탕으로 회사의 내년도 수익 예측하기</p>
<ul>
<li>(회귀)regression 작업</li>
<li>#선형회귀 #다항회귀 #회귀 SVM #회귀 랜덤 포레스트 #인공 신경망</li>
<li>과거 성과 데이터를 고려하고 싶다면</li>
<li>#RNN #CNN #Transformer 사용</li>
</ul>
</li>
<li><p>신용카드 부정 거래 탐지
<strong>이상치 탐지 (outlier detection)</strong> 작업이라고 한다
isolation forest, Gaussian mixture, autoencoder 사용</p>
</li>
<li><p>과거 구매 이력을 기반으로 고객을 나누고 각 집합마다 다른 마케팅 전략 계획하기</p>
<ul>
<li>군집(clustering) 작업</li>
<li>k-means, DBSCAN(밀도 기반 알고리즘) 사용</li>
</ul>
</li>
<li><p>지능형 게임 봇 만들기</p>
<ul>
<li>강화 학습(reinforcement learning) 이용</li>
<li>시간이 지나면 주어진 환경에서 보상이 최대가 되는 행동을 선택하는 에이전틀를 훈련하는 머신러닝의 한 분야</li>
<li>알파고가 강화 학습을 사용하여 구축됨</li>
</ul>
</li>
</ul>
<h1 id="14-🔥머신러닝-시스템의-종류">1.4 🔥머신러닝 시스템의 종류</h1>
<p>  종류가 많으면 항상 분류하는 <strong>기준</strong>이 존재한다. </p>
<ul>
<li>1.4.1 ) 훈련 지도 방식 (학습하는 동안의 지도 형태나 정보량에 따라 분류)<ul>
<li>지도 학습(supervised learning)</li>
<li>비지도 학습(unsupervised learning)</li>
<li>번외) 준지도 학습(semi-supervised learning)</li>
<li>자기 지도 학습(self-supervised learning)</li>
<li>강화 학습(reinforcement learning)</li>
</ul>
</li>
<li>1.4.2 ) 실시간으로 점진적인 학습을 하는지 아닌지<ul>
<li>온라인 학습</li>
<li>배치 학습</li>
</ul>
</li>
<li>1.4.3 ) 예측 방식에 따른 차이<ul>
<li>사례 기반 학습(알고 있는 데이터 포인트와 새 데이터 포인트 비교)</li>
<li>모델 기반 학습(훈련 데이터셋에서 패턴 발견하여 예측 모델 구축)</li>
</ul>
</li>
</ul>
<h1 id="15-🔥머신러닝의-주요-도전-과제">1.5 🔥머신러닝의 주요 도전 과제</h1>
<h2 id="151-충분하지-않은-양의-훈련-데이터">1.5.1 충분하지 않은 양의 훈련 데이터</h2>
<p> 대부분의 머신러닝 알고리즘이 잘 작동하려면 데이터가 많아야 한다!! 아주 간단한 문제라도 수천 개의 데이터가 필요하니, 더 복잡한 분야(이미지나 음성 인식)에서는 더 많은 데이터가 필요하다.</p>
<blockquote>
<p>책에서 마이크로소프트 연구자인 Michele Banko와 Eric Brill은 2001년에 발표한 <a href="https://dl.acm.org/doi/10.3115/1073012.1073017">논문</a>을 언급했다.</p>
</blockquote>
<p> 결론(6.conclusion) 부분을 읽어보면 자연어 분류 작업에서 더 큰 학습데이터를 사용하면 성능이 크게 향상될 수 있음을 보여줄 있다고 언급한다. 따라서 다양한 학습 알고리즘을 비교하는 연구에 집중하기 보다는 더 큰 labeld dataset을 구축하는 데 중점을 두어야 한다고 말하고 있다. </p>
<ul>
<li>corpus : 연구나 학습을 위해 모아놓은 텍스트 데이터의 집합, 보통 NLP에서 사용되며, 언어를 학습하거나 알고리즘을 테스트할 때 필요한 데이터셋을 의미함.</li>
</ul>
<p>2009년 Peter Norvig 등이 쓴 「The Unreasonbale Effectiveness of Data」<a href="https://static.googleusercontent.com/media/research.google.com/ko//pubs/archive/35179.pdf">논문</a>에서도 비슷한 주장을 언급하고 있다.</p>
<h2 id="152-대표성-없는-훈련-데이터">1.5.2 대표성 없는 훈련 데이터</h2>
<p> 일반화가 잘 되려면 훈련 데이터가 일반화하고 싶은 새로운 사례를 대표하는 것이 중요하다. 하지만 이런 훈련 세트를 찾는 것은 어렵다. 결측값이 많은 데이터를 다루어서 그런가 싶었는데, 대표성을 띄는 샘플을 찾기 어려워서 그렇다고 한다.</p>
<p> 샘플이 작으면 sampling noise(우연에 의한 대표성 없는 데이터)가, 표본 추출 방법이 잘못되면 아무리 큰 샘플이라도 sampling bias가 일어나서 대표성을 띄지 못할 수 있다고 한다.</p>
<h2 id="153-낮은-품질의-데이터">1.5.3 낮은 품질의 데이터</h2>
<p>정제되어 있지 않은 데이터에서는 특정한 패턴을 찾기 어렵다. (캐글 조금만 해보면 정말 공감할 수밖에 없는 내용일 것 같다. 점수가 안 나와...)</p>
<h2 id="154-관련-없는-특성">1.5.4 관련 없는 특성</h2>
<blockquote>
<p><strong>특성 공학(feature engineering)</strong> : 훈련에 사용할 좋은 특성을 찾는 것</p>
</blockquote>
<ul>
<li><p>*<em>특성 선택(feature selection) *</em></p>
<ul>
<li>가지고 있는 특성 중에서 훈련에 가장 유용한 특성 선택</li>
</ul>
</li>
<li><p><strong>특성 추출(feature extraction)</strong></p>
<ul>
<li>특성을 결합해서 더 유용한 특성 만들기(차원 축소 알고리즘에도 도움이 될 수 있다고 함!)</li>
</ul>
</li>
<li><p><strong>데이터 수집</strong></p>
<ul>
<li>새로운 데이터를 수집해서 새로운 특성을 만든다</li>
</ul>
<h2 id="155-훈련-데이터-과대적합">1.5.5 훈련 데이터 과대적합</h2>
</li>
</ul>
<blockquote>
<p>과대적합(overfitting) : 모델이 훈련 데이터에는 너무 잘 맞지만 일반성이 떨어지는 경우,훈련 데이터의 양과 잡음에 비해 모델이 너무 복잡할 때 일어난다!</p>
</blockquote>
<p>과대적합 방지</p>
<ol>
<li><p>파라미터 수가 적은 모델 택하기</p>
</li>
<li><p>훈련 데이터 더 많이 모으기</p>
</li>
<li><p>훈련 데이터의 잡음 제거(오류 데이터 수정과 이상치 제거)</p>
</li>
<li><p>규제(regularization) : 제약 가하기
 ex) 선형모델에서 파라미터 조절(자유도 degree of freedom)</p>
<p>규제의 양은 hyperparameter가 결정함. 
*참고로 이 하이퍼파라미터는 모델이 아닌 학습 알고리즘의 파라미터이기에 훈련 전에 상수로 지정되어 남아 있는다고 한다.</p>
</li>
</ol>
<h2 id="156-훈련-데이터-과소적합">1.5.6 훈련 데이터 과소적합</h2>
<blockquote>
<p>과소적합(underfitting) : 모델이 너무 단순해서 데이터의 내재된 구조를 학습하지 못할 때 일어남.</p>
</blockquote>
<p>과소적합 방지</p>
<ol>
<li><p>모델 파라미터가 더 많은 강력한 모델 선택</p>
</li>
<li><p>학습 알고리즘에 더 좋은 특성 제공(특성 공학)</p>
</li>
<li><p>모델의 제약 줄이기(ex. 규제 하이퍼파라미터 감소시키기)</p>
<h1 id="16-🔥-테스트와-검증">1.6 🔥 테스트와 검증</h1>
<blockquote>
<p>모델이 샘플에 얼마나 잘 일반화될지 알려면 실제로 적용해보는 수밖에 없다! 하지만 실제로 적용했다가 만약 모델 성능이 않 좋다면 자칫 욕만 얻어먹을 수 있다! 실제 적용하는 대신 더 나은 방법들도 존재한다.</p>
</blockquote>
<p><code>훈련 세트</code>와 <code>테스트 세트</code> 2개로 나누는 방법이 있다. 
일반화 오차(generalization error) = 외부 샘플 오차(out-of-sample error) : 새로운 샘플에 대한 오차 비율</p>
<p>테스트 세트에서 모델을 평가함으로써 이 오차에 대한 추정값(estimation)을 얻을 수 있다. 이 수치를 통해 한 번도 본 적이 없는 새로운 샘플을 모델이 어떻게 작동할 지 볼 수 있다고 한다.</p>
<p>만약 훈련 오차↓, 일반화 오차 ↑ 상황이라면 <strong>과대적합</strong>이 일어난 상황으로 볼 수 있다.</p>
</li>
</ol>
<h2 id="161-하이퍼파라미터-튜닝과-모델-선택">1.6.1 하이퍼파라미터 튜닝과 모델 선택</h2>
<blockquote>
<p>모델 평가 -** 테스트 세트**를 이용하자!</p>
</blockquote>
<blockquote>
<p>100개의 하이퍼파라미터 값으로 100개의 다른 모델을 훈련시키는 방법이 있다. 일반화 오차가 가장 낮은 모델을 최적의 하이퍼파라미터를 찾았다고 가정해보자. 이 모델이 실제 서비스에 투입되면 어느 정도의 성능을 낼 수 있을까?</p>
</blockquote>
<p>일반화 오차를 테스트 세트에서 여러 번 측정했기에,
*<em>이미 테스트 세트에 최적화된 모델이 되버린 상태다. *</em>
따라서 모델이 새로운 데이터, 즉 실제 서비스에 투입되면 잘 작동하지 않을 수 있다!</p>
<blockquote>
<p>어떻게 해결하지? <code>홀드아웃 검증 holdout validation</code></p>
</blockquote>
<p>훈련 세트의 일부를 떼어내어 여러 후보 모델을 평가하고 가장 좋은 하나를 선택하는 방법</p>
<p>새로운 홀드아웃 세트 : 검증 세트 (<strong>validation set</strong>)
<em><strong>개발 세트(development set), 데브 세트(dev set)</strong> 라고도 함!</em></p>
<p>검증 세트가 너무 작거나 너무 크면 당연히 문제가 생긴다. 적절한 양을 찾는 것이 가장 중요하다!</p>
<p>검증 세트가 너무 커서 남은 훈련 세트가 전체 훈련 세트보다 작아지면, 너무 작은 훈련 세트에서 훈련한 모델을 비교하는 것은 이상적이지 않다고 한다. 이를 해결하기 위해 작은 검증 세트를 사용해 여러 개를 사용하는 <a href="https://velog.io/@yoonie_03/ML-K-fold-vs-StratifiedKFold">교차 검증( cross-validation)</a>이라는 방법을 사용할 수 있다.</p>
<p><code>교차 검증으로 쓰이는 두 기법에 대한 내용을 정리한 글이 있으니 참고하면 좋을 것 같다!</code></p>
<p>다만, 훈련 시간이 검증 세트의 개수에 비례해서 늘어난다는 단점이 존재한다! </p>
<h2 id="162-데이터-불일치">1.6.2 데이터 불일치</h2>
<p>데이터를 아무리 많이 얻더라도, 대표성을 띄지 않는다면 무용지물일 수 잇다. </p>
<p>만약에 버섯 사진으로 버섯의 종류를 찾는 모바일 앱을 만든다고 해보자. 웹에서 엄청난 양의 버섯 사진을 구할 수 있으나, 실제로 찍을 사진을 대신하지는 못 한다. </p>
<p>이 경우를 대비하여 대표성을 가진 사진의 반을 검증 세트에, 반을 테스트 세트에 넣었고, 모델 성능을 측정했는데 결과가 실망스러웠다고 생각해보자. 이 경우엔 훈련 세트에 과대적합이 일어난 것인지, 웹 사진과 앱 사진의 데이터가 불일치하기 때문인지 알기 어렵다고 한다. </p>
<p>이를 해결하기 위해 한 가지 방법이 있다. 훈련 사진의 일부를 떼어내 또 다    른 세트, <strong>훈련-개발 세트(train-dev set, 앤드류 응은 이렇게 불렀다고 한다)</strong>를 만드는 것이다. 훈련 세트에서 훈련한 후, 훈련-개발 세트에서 잘 작동하는지 평가한다고 한다.</p>
<p>이때 모델 잘 작동 X → 검증 세트에서 평가
모델 성능 X → 데이터 불일치 문제(전처리 필요)</p>
<h3 id="공짜-점심-이론">공짜 점심 이론</h3>
<blockquote>
</blockquote>
<p><strong><em><a href="https://ieeexplore.ieee.org/document/6795940">The Lack of A Priori Distinctions Between Learning Algorithms</a></em></strong></p>
<p>특정 종류의 모델을 선택할 때 데이터에 대한 암묵적인 가정(assumption)을 하는 것이 이 이론의 주 내용이다._** David Wolpert<strong>_는 데이터에 대해 완벽하게 아무런 가정도 하지 않으면 한 모델을 다른 모델보다 선호할 근거가 없음을 보였다. 이를 **no free lunch(NFL)</strong> 이론이라고 한다. 경험하기 전에 더 잘 맞을 것이라 확신할 수 없기에 <strong>어떤 모델이 최선인지 확실히 알려면 모든 모델을 평가해보는 것뿐</strong>이라고 주장한다.</p>
<p>물론 이건 불가능하기에 실전에서는 데이터에 대한 타당한 가정을 하고 적절한 모델 몇 가지만 평가한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[optimization] Convex]]></title>
            <link>https://velog.io/@yoonie_03/optimization-Convex</link>
            <guid>https://velog.io/@yoonie_03/optimization-Convex</guid>
            <pubDate>Wed, 14 Aug 2024 12:44:34 GMT</pubDate>
            <description><![CDATA[<p>최적화에서 <strong>Convex</strong>가 그렇게 중요하다고 들은 기억이 있어서 정리해 보려고 한다.</p>
<blockquote>
<p>Convex? Convex set?</p>
</blockquote>
<p>우선 <strong>Convex set</strong>이란
기하학 및 최적화 이론에서 중요한 개념으로, 임의의 두 점을 선택했을 때 이 두 점을 연결하는 선분이 항상 그 집합 내부에 포함되는 집합을 말한다.</p>
<p>조금 더 공식적으로 설명하자면, 
$S$라는 집합이 유클리드 공간 또는 벡터 공간 내에 있다고 할 때, 만약 임의의 두 점 $x$와 $y$가 $S$에 속한다면,  $x$와 $y$ 사이를 연결하는 모든 점들이 $S$에 속하면 $S$는 <strong>convex set</strong>이라고 한다.</p>
<p>이를 식으로 표현하면 아래와 같다!
$$
z=\lambda x +(1-\lambda)y
$$
단 여기서 $\lambda$는 $0 \leq \lambda \leq 1$를 만족하는 실수다</p>
<p>대표적인 Convex set의 예를 찾는다면 2차원 평면에서의 원, 정사각형, 삼각형 등이 있다. </p>
<p>전역 최적해의 보장
Convex 함수에서 최적화 문제를 풀 때, 전역 최적해를 쉽게 찾을 수 있다!</p>
<p>Convex 집합에서 정의된 convex 함수는 극소점이 반드시 전역 최소점임을 보장합니다. 즉, 함수 $f(x)$가 convex이고 정의역이 convex 집합 $C$라면, $f(x)$의 모든 극소점은 동시에 전역 최소점이 된다</p>
<p>이는 최적화 문제를 풀 때, 탐색하는 해가 지역 최적해에 갇히는 문제가 없음을 의미합니다. 이 때문에 convex 함수는 최적화 문제에서 많이 선호된다</p>
<blockquote>
<p>그래서 왜 중요한데?</p>
</blockquote>
<center>Convex 함수에서는 그 지점에서 미분계수가 0인 것과 최소인 것이 필요충분조건 관계를 가진다
<br></br> 정말 간단하게 말하자면 극소값이 곧 최소값이 되기 때문이다!!</center>

<p>그래서 많은 <strong>non-convex</strong> 문제들을 <strong>convex</strong> 문제로 바꾸려는 시도가 많이 있다고 한다.</p>
<blockquote>
<p><strong>Convex</strong> 에서 local minimum = global minimum인 것을 증명해보자</p>
</blockquote>
<p>먼저 $f(x)$가 Convex이고 feasible set $F$가 Convex이고
$f(x^*)$ : local minimum, $f(x&#39;)$는 local minimum이 아닌 최솟값이라고 해보자.</p>
<p>그렇다면 $f(x&#39;) &lt; f(x^*)$ 이런 관계가 성립한다고 출발할 수 있다.
또한 convex 조건에 따라 아래의 식이 성립한다.</p>
<p>$$
\alpha x^* +(1-\alpha)x&#39; \in F
$$</p>
<p>$f(x&#39;) &lt; f(x^*)$ 이기에  아래와 같은 식이 성립한다.</p>
<p>$$
f(\alpha x^* +(1-\alpha)x&#39;) \leq \alpha f(x^<em>) + (1-\alpha)f(x&#39;)
$$
우변에 $f(x^</em>)$를 더하고 다시 빼주자</p>
<p>$$
f(\alpha x^* +(1-\alpha)x&#39;) \leq \alpha f(x^<em>) + (1-\alpha)f(x&#39;) +f(x^</em>) -f(x^*)
$$</p>
<p>$(1-\alpha)$ 항을 기준으로 식을 정리하자</p>
<p>$$
f(\alpha x^* +(1-\alpha)x&#39;) \leq f(x^<em>) + (1-\alpha)(f(x&#39;) -f(x^</em>)
$$</p>
<p>여기서 $f(x&#39;) &lt; f(x^<em>)$ 이기에 $f(x&#39;) -f(x^</em>) &lt; 0$이다.
또한 $0 \leq \alpha \leq 1$ 이기에 $(1-\alpha)$ 항은 항상 양수를 가진다.</p>
<p>따라서 $(1-\alpha)(f(x&#39;) -f(x^<em>)$ 항은 항상 *</em>음수** 값을 가지게 된다.</p>
<p>$$
f(\alpha x^* +(1-\alpha)x&#39;) \leq f(x^<em>) + (1-\alpha)(f(x&#39;) -f(x^</em>) &lt; f(x^*)
$$
그래서 이와 같은 관계가 성립해야 한다</p>
<p>이제 가장 왼쪽의 식을 보자! $\alpha$가 1에 가까워질수록 $f(\alpha x^* +(1-\alpha)x&#39;)$식은 $f(x^<em>)$값에 가까워진다. 하지만 이러면 *</em>모순**이다!</p>
<p>$f(x^<em>)$는 local minimum  값이다. 즉 <strong>주변에서 최소값</strong>을 가진다는 것이다. 
하지만 $f(\alpha x^</em> +(1-\alpha)x&#39;)$ 이 식은 $x^<em>$주변을 보니 $x^</em>$보다 더 작은 값이 있다고 말하고 있다. </p>
<p>따라서 기존의 전제, $f(x&#39;) &lt; f(x^*)$ 는 모순이 잇다.</p>
<p>여기서 set F가 feasible한 set이란 것이 제일 중요하다.
왜냐하면 이 조건이 없다면 다른 조건에 제약을 받게 되어서 $f(x&#39;) &lt; f(x^*)$ 이 식이 성립할 수도 있기 때문이다. </p>
<p>따라서</p>
<blockquote>
<p>local minimum point : feasible sol. 중에 주변에서 가장 작게 만드는 것
이라고 정리할 수 있다!</p>
</blockquote>
<hr>
<p>다른 증명 버전</p>
<h1 id="🟦-convex-function의-정의">🟦 Convex Function의 정의</h1>
<p>함수 $f: \mathbb R^n \to \mathbb{R}$가 <strong>convex</strong>하다는 것은, 임의의 $x, y$ $\in \mathbb{R}^n$와 $\lambda \in [0, 1]$에 대해 다음 부등식이 성립함을 의미한다</p>
<p>$$
f(\lambda x + (1 - \lambda) y) \leq \lambda f(x) + (1 - \lambda) f(y)
$$</p>
<p>이 부등식은 함수 $f$의 그래프가 두 점 $x$와 $y$를 잇는 직선보다 아래에 있음을 의미합니다. 이런 함수가 <strong>convex</strong> 함수다</p>
<h3 id="극소값과-최소값의-개념">극소값과 최소값의 개념</h3>
<ul>
<li><p><strong>극소값 (local minimum):</strong> 함수 $f$의 한 점 $x^<em>$가 극소점이 되려면, $x^</em>$의 어떤 작은 근방에서$f(x^*) \leq f(x)$를 만족하는 $x$가 존재해야 한다</p>
</li>
<li><p><strong>최소값 (global minimum):</strong> 함수 $f$의 한 점 $x^<em>$가 최소점이 되려면, $f(x^</em>) \leq f(x)$가 모든 $x \in \mathbb{R}^n$에 대해 성립해야 한다</p>
</li>
</ul>
<h3 id="증명-convex-function에서-극소값이-최소값이-됨">증명: Convex Function에서 극소값이 최소값이 됨</h3>
<p>$f$가 convex 함수이고, $x^<em>$가 $f$의 극소점이라고 가정하자,
이제,$x^</em>$가 최소점임을 보이기 위해 $x^*$가 최소점이 아니라면 모순이 생긴다는 것을 증명하겠다!</p>
<ol>
<li><p>$x^<em>$가 극소점이므로, $\exists \delta &gt; 0$에 대해 $f(x^</em>) \leq f(x)$ for all $|x - x^*| &lt; \delta$</p>
</li>
<li><p>$x^<em>$가 최소점이 아니라고 가정,
즉, $f(x^</em>) &gt; f(y)$인 어떤 점 $y$가 존재한다고 하자</p>
</li>
<li><p>이제 $x^<em>$와 $y$ 사이의 선분을 고려, $\lambda \in [0, 1]$에 대해, 
$z = \lambda x^</em> + (1 - \lambda) y$라 하면, *<em>convex *</em>함수의 정의에 따라:</p>
<p>$$
f(z) \leq \lambda f(x^*) + (1 - \lambda) f(y)
$$</p>
</li>
<li><p>$0 &lt; \lambda &lt; 1$인 경우를 고려하면,$f(y) &lt; f(x^*)$이므로:</p>
<p>$$
\lambda f(x^<em>) + (1 - \lambda) f(y) &lt; f(x^</em>)
$$</p>
<p>따라서 $f(z) &lt; f(x^<em>)$가 된다! 이는 $z$가 $x^</em>$의 근방 내에 있으면서도 $f(z) &lt; f(x^*)$를 만족하게 된다</p>
</li>
<li><p>그러나, 이는 $x^<em>$가 극소점이라는 가정에 모순이 된다 왜냐하면 극소점에서는 그 근방에서 $f(x^</em>) \leq f(z)$이어야 하기 때문이다</p>
</li>
</ol>
<p>따라서, $x^*$가 convex 함수 $f$의 극소점이라면, 그것은 반드시 최소점이 됩니다. 이로써 convex 함수에서는 극소값이 곧 최소값이 된다는 것이 증명되었다</p>
<hr>
<h1 id="🟦-convex와-경사하강법">🟦 Convex와 경사하강법</h1>
<p><strong>경사하강법(Gradient Descent)</strong>은 최적화 문제를 푸는 매우 일반적인 방법입니다. 경사하강법은 함수의 기울기(그래디언트)를 따라 내려가면서 최소점을 찾는 알고리즘입니다. Convex 함수에서 경사하강법이 특히 유용한 이유는 다음과 같습니다:</p>
<p>단일 극소점: Convex 함수는 극소점이 하나뿐이며, 그 극소점이 곧 전역 최소점입니다. 경사하강법을 사용할 때, 초기값에 관계없이 이 전역 최소점에 도달할 수 있습니다. 즉, 경사하강법이 수렴하는 해는 최적해임이 보장됩니다.</p>
<p>효율성: Convex 함수의 성질 덕분에 경사하강법이 비교적 빠르고 안정적으로 수렴합니다. 특히, 강한 convex성(strong convexity)을 갖는 함수에서는 수렴 속도가 더 빨라집니다.</p>
<p>단순성: Convex 함수에서는 경사하강법이 복잡한 최적화 알고리즘 없이도 쉽게 구현할 수 있으며, 그 결과의 신뢰성이 높습니다.</p>
<h3 id="경사-하강법-작동-과정">경사 하강법 작동 과정</h3>
<ol>
<li><p><strong>초기점 설정</strong>: 최적화를 시작할 초기점 $x_0$를 설정</p>
</li>
<li><p><strong>기울기 계산</strong>: 현재 위치 $x_t$에서의 기울기 $\nabla f(x_t)$를 계산합니다.</p>
</li>
<li><p><strong>갱신</strong>: 기울기의 반대 방향으로 한 걸음 나아갑니다. 갱신 식은 다음과 같다</p>
</li>
</ol>
<p>$$
x_{t+1}=x_t - \alpha \bigtriangledown f(x_t)
$$</p>
<p>여기서 $\alpha$는 학습률(learning rate)로, 한 걸음의 크기를 결정</p>
<ol start="4">
<li><strong>수렴</strong>: 더 이상 크게 변화하지 않을 때까지, 또는 미리 정의된 조건을 만족할 때까지 이 과정을 반복</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] Multiclass Classification]]></title>
            <link>https://velog.io/@yoonie_03/ML-Multiclass-Classification</link>
            <guid>https://velog.io/@yoonie_03/ML-Multiclass-Classification</guid>
            <pubDate>Wed, 07 Aug 2024 01:30:47 GMT</pubDate>
            <description><![CDATA[<h1 id="1-다중-분류🔥">1. 다중 분류🔥</h1>
<p>2개 이상의 클래스로 분류하는 것을 다중 분류라고 한다.</p>
<p><strong>Random Forest classifiers</strong>와 <strong>Bayes classifiers = multinomial classifiers</strong>의 경우, 다중 분류가 가능하다.</p>
<p>하지만 <strong>Support Vector Machine classifiers</strong>와 <strong>Linear classifiers</strong>는 이진 분류에만 한정된다.</p>
<p>하지만 여러 개의 이진 분류기를 통해 다중 분류하는 것도 가능하다.</p>
<h2 id="1-ova-전략">1) OvA 전략</h2>
<blockquote>
<p><strong>One-versus-all</strong>
OvR 방식 (One-versus-Rest)이라고도 불린다.</p>
</blockquote>
<p>OvA 전략은 <strong>각 클래스마다 하나의 이진 분류기를 훈련</strong>시킨 후, 분류할 때 모든 분류기의 결정 점수를 비교하여 가장 높은 점수를 가진 분류기의 클래스를 선택하는 방식이다.</p>
<p>예를 들어 0부터 9까지의 숫자를 다중 분류하고자 할 때는 10개의 이진 분류기를 이용하면 된다. (0 검출기, 1 검출기...) 이미지 분류 시엔 해당 이미지에 대한 결정 점수를 받아 가장 높은 점수를 출력하는 분류기의 클래스를 선택한다.</p>
<h2 id="2-ovo-전략">2) OvO 전략</h2>
<blockquote>
<p><strong>One-versus-one</strong></p>
</blockquote>
<p>OvO 전략은 <strong>모든 클래스 쌍마다 이진 분류기를 훈련</strong>시켜, 최종 분류 시 각 분류기 결과를 비교하여 가장 많이 득표한 클래스를 선택하는 방식이다.</p>
<p>N개의 클래스가 있다면 $\frac{N \times (N-1)}{2}$개의 분류기를 훈련시키게 된다. 예를 들어 0부터 9까지의 숫자를 분류하고자 할 땐 45개의 분류기가 만들어진다. 이미지 분류 시엔 해당 이미지를 이 45개의 분류기에 모두 통과시켜서 가장 많이 득표한 클래스를 선택한다.</p>
<h2 id="3-ova-ovo-선택-전략">3) OvA OvO 선택 전략</h2>
<p>일부 알고리즘(SVM 분류기)은 훈련 세트의 크기에 따라 성능이 저하된다. 그래서 이러한 알고리즘의 경우 작은 훈련 세트에서 많은 분류기를 훈련시키는 OvO가 선호된다.</p>
<p><strong>그러나 대부분의 이진 분류 알고리즘의 경우 OvA가 선호된다.</strong></p>
<blockquote>
<p>Scikit-Learn의 자동 전략 선택</p>
</blockquote>
<p>Scikit-Learn은 사용자가 이진 분류 알고리즘을 다중 클래스 분류에 사용하려고 할 때 이를 감지하여 자동으로 OvA 전략을 적용한다. 다만, SVM 분류기인 경우에는 OvO 전략을 사용한다.</p>
<blockquote>
<p>장점</p>
</blockquote>
<p><strong>유연성</strong>: 기본적으로 모든 이진 분류기를 사용할 수 있으므로, 다양한 분류 알고리즘을 쉽게 확장할 가능하다. (그렇게 나온게 위의 함수다)</p>
<p><strong>단순함</strong>: 다중 클래스 문제를 이진 분류 문제로 변환하므로, 구현이 상대적으로 단순하다!</p>
<blockquote>
<p>단점</p>
</blockquote>
<p><strong>효율성 문제</strong>: 클래스가 많아지면 그만큼 이진 분류기도 많아지기에 비용 측면에서 효과적이지 않을 수 있다.</p>
<p><strong>불균형 데이터</strong>: 특정 클래스가 다른 클래스보다 훨씬 적은 경우, 해당 클래스와 나머지 클래스를 비교할 때 불균형 문제가 발생할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] ROC Curve]]></title>
            <link>https://velog.io/@yoonie_03/ML-ROC-Curve</link>
            <guid>https://velog.io/@yoonie_03/ML-ROC-Curve</guid>
            <pubDate>Wed, 07 Aug 2024 01:29:04 GMT</pubDate>
            <description><![CDATA[<h1 id="1-roc-curve🔥">1. ROC Curve🔥</h1>
<blockquote>
<p><strong>R</strong>eceiver <strong>o</strong>perating <strong>c</strong>haracteristic</p>
</blockquote>
<p>ROC Curve는 이진 분류기에서 성능을 평가하는 데 자주 사용되는 도구다. 정밀도/재현 커브와 유사하지만, 여기서는 참 양성 비율(TPR)과 거짓 양성 비율(FPR)을 사용하여 그래프를 그린다.</p>
<p>거짓 양성 비율(FPR)은 실제로는 음성인 데이터가 모델에서 양성으로 잘못 예측한 비율을 의미한다. 이 값은 참 음성 비율(TNR)에서 1을 뺀 값과 같다.</p>
<p>TNR-1=FPR</p>
<p>실제로 음성인 데이터들
음성으로 예측 비율 - 1 = 양성으로 예측</p>
<blockquote>
<p>이 참 음성 비율(TN)은 특이도(<strong>specificity</strong>)라고도 불린다.</p>
</blockquote>
<p>따라서 ROC Curve는 <strong>민감도(재현율) vs (1-특이도)</strong>를 그래프로 나타낸다.
곡선 아래 면적(ACU, Area Under the Curve)은 모델의 전체 성능을 나타낸다. ACU 값이 클수록 모델의 성능이 좋다고 판단할 수 있다.</p>
<h1 id="2roc-curve-vs-pr-curve-🔥">2.ROC Curve vs PR curve 🔥</h1>
<p>위의 두 요소는 비슷한 역할을 한다.</p>
<p><strong>일반적으로, 드문 양성 클래스나 거짓 양성에 더 신경 쓰는 경우에는 PR 곡선이 더 유용하다. 반면, 그 외의 경우에는 ROC 곡선이 적합할 수 있다.</strong></p>
<p>ROC 곡선과 ACU이 좋다고 해서 무조건 모델의 성능이 좋다고 볼 수 없다.</p>
<p>양성 샘플이 음성 샘플에 비해 적어서 이런 현상이 발생할 수 있다. <strong>ROC 곡선은 클래스 불균형 문제를 제대로 반영하지 못할 수 있다</strong>.</p>
<p>PR 곡선은 <strong>모델의 성능이 아직 개선될 수 있음</strong>을 분명히 보여준다. PR 곡선이 오른쪽 상단 모서리에 가까울수록 모델의 성능이 더 좋다는 것을 의미한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] Confusion Matrix와 이용]]></title>
            <link>https://velog.io/@yoonie_03/Confusion-Matrix%EC%99%80-%EC%9D%B4%EC%9A%A9</link>
            <guid>https://velog.io/@yoonie_03/Confusion-Matrix%EC%99%80-%EC%9D%B4%EC%9A%A9</guid>
            <pubDate>Wed, 07 Aug 2024 01:27:16 GMT</pubDate>
            <description><![CDATA[<h1 id="1-confusion-matrix-혼동행렬">1. Confusion Matrix (혼동행렬)</h1>
<blockquote>
<p>혼동 행렬을 이용해서 모델을 평가할 수 있다.</p>
</blockquote>
<p>혼동 행렬을 계산하려면 모델이 예측한 값들과 실제 값들이 필요하다. 테스트 세트에서 예측할 할 수 있긴 하지만 보통 테스트 세트는 프로젝트의 마지막 단계에서 최종 평가용으로 이용한다. 개발 과정 중에 테스트 세트를 사용하면 모델이 테스트 데이터에 과적합될 수 있기 때문이다.</p>
<p>테스트 세트를 사용하지 않고도 <code>cross_val_predict()</code> 함수를 이용하여 예측값을 얻을 수 있다. 이 함수는 교차 검증(cross-validation)을 수행하면서 각 폴드(fold)에 대해 예측을 생성한다. <code>cross_val_score</code> 함수처럼 <code>cross_val_predict()</code> 함수는 <strong>K-fold</strong> 교차 검증 기법을 이용한다. </p>
<pre><code class="language-python">from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix

# 모델 학습 및 예측
y_pred = cross_val_predict(classifier, X, y, cv=5)

# 혼동 행렬 계산
conf_matrix = confusion_matrix(y, y_pred)
print(conf_matrix)</code></pre>
<p>sk-learn에서 실행해보면 행렬이 나오게 된다.</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center"><center>Predicted Positive</center></th>
<th align="center"><center>Predicted Negative</center></th>
</tr>
</thead>
<tbody><tr>
<td align="center">Actually Positive</td>
<td align="center"><strong>T</strong>rue <strong>P</strong>ositives</td>
<td align="center"><strong>F</strong>alse <strong>N</strong>egatives</td>
</tr>
<tr>
<td align="center">Actually Negative</td>
<td align="center"><strong>F</strong>alse <strong>P</strong>ositives</td>
<td align="center"><strong>T</strong>rue <strong>N</strong>egatives</td>
</tr>
</tbody></table>
<p>각각의 숫자는 위의 표에 대입해서 생각하면 된다. 성능이 좋을수록 왼쪽 위에서 내려오는 대각선에 위치한 값들에 더 많은 숫자가 존재하게 된다.</p>
<h1 id="2-precision-정밀도">2. Precision (정밀도)</h1>
<p>혼동 행렬은 많은 정보를 주지만, 간결한 정보를 얻고자 할 때 precision(정밀도)를 이용하게 된다.</p>
<p>$$
precision = \frac{TP}{TP+FP}
$$</p>
<p>TP : 실제 양성인데, 양성으로 판별된 경우
FP : 실제 음성인데, 양성으로 판별된 경우
→ 양성으로 판별된 경우에 얼마나 잘 맞추는지 확인할 수 있음.</p>
<h1 id="3-recall-재현율">3. Recall (재현율)</h1>
<p>분류기가 하나의 양성 인스턴스만을 고려하고 나머지 양성 인스턴스를 모두 무시하는 상황에서는 유용할 수 없다. 이는 특히 불균형 데이터셋에서 문제가 될 수 있다. 그래서 정밀도는 <strong>재현율</strong>이라 불리는 것과 함께 사용된다.</p>
<p>$$
recall = \frac{TP}{TP+FN}
$$</p>
<p>TP : 실제 양성인데, 양성으로 판별된 경우
FN : 실제 양성인데, 음성으로 판별된 경우
→ 실제 양성인 경우에 모델이 얼마나 잘 판별하는지 볼 수 있음</p>
<h1 id="4-f_1-score">4. $F_1$ score</h1>
<p>편의를 위해 정밀도와 재현율을 결합한 형태가 있는데, 그게 바로 $F_1 score$다</p>
<p>$$
F_1 = \frac{2}{\frac{1}{precision}+\frac{1}{recall}}= 2 , \times \frac{precision \times recall}{precision+recall} = \frac{TP}{TP+\frac{FN+FP}{2}}
$$</p>
<p>F1 스코어는 정밀도와 재현율의 조화 평균을 계산하는 지표로, 두 값이 균형을 이룰 때 높은 점수를 받게 된다. 상황에 따라 정밀도와 재현율 중 더 중요하게 여겨야 하는 것이 달라진다. </p>
<p>예를 들어, 아이들에게 안전한 비디오를 감지하는 분류기를 훈련시켰다고 가정해보자. 이 경우엔 이 높은 재현율을 가지지만 몇몇 정말 나쁜 비디오가 제품에 나타나는 분류기보다 나을 것이다. 좋은 비디오가 많이 남는 것보다(낮은 재현율) 안전한 비디오만 남길 수(높은 정밀도) 있는 것이 더 중요하기 때문이다.</p>
<p>반면에 감시 영상에서 절도범을 감지하는 분류기를 훈련시켰다고 생각해보자. 99%의 재현율만 유지된다면 정밀도가 30%밖에 되지 않아도 괜찮을 것이다.</p>
<h1 id="5정밀도와-재현율-tradeoff">5.정밀도와 재현율 Tradeoff</h1>
<blockquote>
<p><strong>정밀도 (Precision):</strong> 모델이 양성이라고 예측한 것 중에서 실제 양성의 비율,즉, false positive를 얼마나 줄이는지 측정</p>
</blockquote>
<blockquote>
<p><strong>재현율 (Recall):</strong> 실제 양성 중에서 모델이 양성이라고 정확히 예측한 비율, 즉, false negative를 얼마나 줄이는지 측정</p>
</blockquote>
<blockquote>
<p><strong>F1 스코어:</strong> 정밀도와 재현율의 조화 평균으로, 두 지표의 균형을 중시</p>
</blockquote>
<p>정밀도와 재현율 사이에는 상쇄 관계가 있어서, 하나를 증가시키면 다른 하나는 감소하는 경향이 있다. 이를 정밀도/재현율 Tradeoff라고 부른다.</p>
<h1 id="6-decision-threshold--결정-임계값">6. decision threshold : 결정 임계값</h1>
<p>분류 문제에서 모델이 특정 클래스에 속하는지 여부를 결정하는 데 사용되는 기준값이다. 임계값은 모델의 예측 확률을 기준으로 한다.</p>
<p>예를 들어, 이진 분류에서 모델이 어떤 샘플에 대해 클래스 1(양성 클래스)일 확률을 예측했다고 할 때, 이 확률이 결정 임계값을 초과하면 해당 샘플을 클래스 1로, 그렇지 않으면 클래스 0(음성 클래스)으로 분류합니다.</p>
<blockquote>
<p><strong>임계값 조정</strong></p>
</blockquote>
<p>특정 상황에 따라 이 임계값을 조정하기도 한다. 높은 정밀도가 필요한 경우 임계값을 높이고, 높은 재현율이 필요한 경우 임계값을 낮추면 된다.\</p>
<p>결정 임계값을 높인다는 것은 곧 양성 클래스로 예측하는 기준을 엄격히 한다는 것이다. 그래서 정밀도가 높아질 수는 있지만 정밀도는 낮아지게 된다.</p>
<blockquote>
<p>활용 예시</p>
</blockquote>
<p><strong>스팸 필터링</strong>: 스팸 이메일 분류에서는 정밀도가 중요하다고 볼 수 있다. 임계값을 높여 스팸으로 잘못 분류되는 정상 이메일(false positives)을 줄여야 한다.</p>
<p><strong>암 진단</strong>: 암 검진 시스템에서는 재현율이 더 중요하다고 볼 수 있다. 임계값을 낮추어 암을 놓치는 경우(false negatives)를 최소화해야 한다.</p>
<blockquote>
<p>PR Curve</p>
</blockquote>
<p>R 곡선은 정밀도(Precision) 대 재현율(Recall)을 나타내는 그래프다. 특히 클래스 불균형 문제를 다루는 데 유용하다. PR 곡선이 오른쪽 상단 모서리에 가까울수록 모델의 성능이 더 좋다는 것을 의미한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ML] K-fold vs StratifiedKFold ]]></title>
            <link>https://velog.io/@yoonie_03/ML-K-fold-vs-StratifiedKFold</link>
            <guid>https://velog.io/@yoonie_03/ML-K-fold-vs-StratifiedKFold</guid>
            <pubDate>Wed, 07 Aug 2024 01:22:48 GMT</pubDate>
            <description><![CDATA[<p><strong>교차 검증</strong>은 데이터의 편중을 막기 위해 데이터를 여러 부분으로 나누어 각각의 부분을 학습 및 검증에 사용하는 방법이다.</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/26b0e6bf-f715-4ed2-96d0-bd406d8071fb/image.png" width = 80% disply =block margin = 4> </p>

<p>Scikit-Learn에서는 <code>cross_val_score()</code> 함수를 이용해서 교차 검증 기법을 활용해서 정확도를 측정할 수 있다. y가 이진 클래스 또는 다중 클래스인 경우 이 함수는 <code>StratifiedKFold</code>를 사용한다. 다른 모든 경우, 예를 들어 회귀 문제나 다중 출력 회귀 문제인 경우에는 KFold가 사용된다. </p>
<p>해당 함수의 매개변수 중 <code>cv</code>는 정수값을 넣을 수 있다. 기본값은 5이다. </p>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html">cross_val_score : sk-learn 공식 문서</a></p>
<blockquote>
<p><strong>StratifiedKFold vs K-fold</strong></p>
</blockquote>
<h1 id="1-k-fold">1. K-fold</h1>
<p><strong>K-fold</strong>는 가장 보편적으로 사용되는 교차 검증 기법으로, K개의 데이터 폴드 세트를 만들어서 K번만큼 각 폴드 세트에 학습과 검증 평가를 반복적으로 수행한다.</p>
<p>sk-learn 공식 문서를 읽어보면, <code>cross_val_score()</code>에서 <code>K-fold</code> 사용시엔 <code>shuffle=False</code>로 인스턴스화(초기화)된다고 설명하고 있다. 무작위로 섞이는 것이 없어지니, 분할 자체는 원래 데이터의 <strong>순서대로</strong> 된다는 것을 알 수 있다. </p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/afb27b80-28f9-49f0-af55-dcc922a31d7a/image.png" width = 80% disply =block margin = 4> </p>



<p><a href="https://scikit-learn.org/dev/modules/cross_validation.html">sk-learn cross-validation</a></p>
<h1 id="2-stratifiedkfold">2. StratifiedKFold</h1>
<p><strong>StratifiedKfold</strong>는 K-Fold의 변형으로, 계층화된 폴드를 반환한다. 각 세트는 전체 세트와 거의 동일한 비율의 각 타겟 캘래스 샘플을 포함한다.</p>
<p>데이터의 클래스 분포를 균형 있게 유지하면서 폴드를 나누는 것을 목적으로 하기에, 이 기법은 불균형한 데이터셋에 사용된다. 한 클래스가 다른 클래스보다 훨씬 많은 경우더라도, 각 폴드가 원본 데이터셋의 클래스 분포와 유사하도록 하여 모델이 각 클래스 샘플을 고르게 학습할 수 있도록 도와준다.</p>
<p align="center"><img src = "https://velog.velcdn.com/images/yoonie_03/post/154487c3-0f6d-44d8-8a1a-070371f852c1/image.png" width = 80% disply =block margin = 4> </p>



<blockquote>
<p>데이터 클래스 분포가 불균형하면 왜 문제일까?</p>
</blockquote>
<p>5인 경우와 5가 아닌 경우를 분류하는 이진 분류기를 생각해보자. 이때 전체 10개의 숫자들은 모두 고른 비율로 데이터셋에 들어있기에, 숫자 5가 차지하는 비율은 전체의 10%라고 가정해보자.</p>
<p>만약 모델이 항상 <strong><em>5가 아니다</em></strong> 라고 예측하면 90%의 정확도를 쉽게 도달할 수 있다. 그러나 이는 모델이 실제로 잘 예측하는 것이 아니라 <strong>단지 클래스 불균형을 이용한 것</strong>에 불과하다.</p>
<p>데이터셋의 불균형으로 인해 <code>Accuracy</code> 항목은 성능 평가에 항상 적합할 수 없다. 높은 정확도가 곧 모델이 실제로 잘 작동한다는 것을 의미하지는 않는다. 정밀도(precision), 재현율(recall), F1-score 등 다른 평가 지표를 사용하는 것이 더 적절할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모두의 딥러닝 14장 model]]></title>
            <link>https://velog.io/@yoonie_03/%EB%AA%A8%EB%91%90%EC%9D%98-%EB%94%A5%EB%9F%AC%EB%8B%9D-14%EC%9E%A5-model</link>
            <guid>https://velog.io/@yoonie_03/%EB%AA%A8%EB%91%90%EC%9D%98-%EB%94%A5%EB%9F%AC%EB%8B%9D-14%EC%9E%A5-model</guid>
            <pubDate>Sun, 21 Jan 2024 08:01:03 GMT</pubDate>
            <description><![CDATA[<h2 id="💻-와인의-종류-예측하기--데이터-확인과-실행">💻 와인의 종류 예측하기 : 데이터 확인과 실행</h2>
<pre><code class="language-python">from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import ModelCheckpoint, EarlyStopping

import pandas as pd
import numpy
import tensorflow as tf
import matplotlib.pyplot as plt

df_pre = pd.read_csv(&#39;/content/drive/MyDrive/AI_WINTER_STUDY/wine.csv&#39;, header=None)

#sample() 원본 데이터에서 정해진 비율만큼 랜덤으로 뽑아오는 함수
#frac = 1이면 원본 데이터의 100% 불러오는 함수
df = df_pre.sample(frac=1) 
print(df.head(5))</code></pre>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/65489ed0-4e0b-49f8-8ed8-66a5d91d4fcf/image.png" width = 80% disply =block margin = 4>
  </p>

<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/420ba7b2-4138-4d14-a64e-33cc07f2aee1/image.png" width = 50% disply =block margin = 4>
  </p>




<pre><code class="language-python"># seed set
seed = 0
numpy.random.seed(seed)
tf.random.set_seed(3)

# data set
dataset = df.values
X = dataset [:,0:12]
Y = dataset [:,12]

# model set
model = Sequential()
model.add(Dense(30, input_dim=12, activation = &#39;relu&#39;))
model.add(Dense(12, activation = &#39;relu&#39;))
model.add(Dense(8, activation = &#39;relu&#39;))
model.add(Dense(1, activation = &#39;sigmoid&#39;))

#model compile
model.compile(loss = &#39;binary_crossentropy&#39;,
              optimizer = &#39;adam&#39;,
              metrics = [&#39;accuracy&#39;])

#model fit
model.fit(X, Y, epochs = 200, batch_size = 200)</code></pre>
<h2 id="💻-모델-업데이트">💻 모델 업데이트</h2>
<pre><code class="language-python">from keras.callbacks import ModelCheckpoint
import os

#model save

MODEL_DIR =&#39;./model/&#39; #모델 저장하는 폴더
if not os.path.exists(MODEL_DIR): #만일 위의 폴더가 존재하지 않으면
  os.mkdir(MODEL_DIR) # 이 이름의 폴더를 만들어 준다

#모델 저장 조건 설정
modelpath = &quot;./model/{epoch:02d} -{val_loss:.4f}.hdf5&quot;

#테스트 오차는 keras 내부에서 val_loss로 기록
#정확도 (acc), 테스트셋 정확도(val_acc), 학습셋 오차(loss)
#함수의 모델이 앞서 저장한 모델보다 나아졌을 때만 저장하기 위해 save_best_only 설정
checkpointer = ModelCheckpoint(filepath = modelpath, monitor = &#39;val_loss&#39;,
                               verbose = 1, save_best_only = True) #verbose = 1, 해당 함수의 진행 사항 출력

                               #모델 학습할 때마다 위에서 정한 checkpointer의 값을 받아서 저장된 곳에 모델 저장
model.fit(X, Y, validation_split=0.2, epochs = 200, batch_size = 200, 
          verbose = 0, callbacks = [checkpointer])</code></pre>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/3ac39e07-908d-4799-9c1f-be3b7381b9bc/image.png" width = 80% disply =block margin = 4>
  </p>


<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/8f767588-3ccb-48a3-8b36-5ae5be11a248/image.png" width = 60% disply =block margin = 4>
   테스트 오차를 실행한 결괏값이 향상되었을 때만 저장되는 것을 확인 가능
  </p>





<h2 id="💻-그래프로-확인">💻 그래프로 확인</h2>
<pre><code class="language-python">#y_vloss에 테스트셋으로 실험 결과의 오차 값을 저장
y_vloss = history.history[&#39;val_loss&#39;]

#y_acc에 학습셋으로 측정한 정확도의 값을 저장
y_acc = history.history[&#39;accuracy&#39;]

#x 값을 저장하고 정확도를 파란색으로, 오차를 빨간색으로 표시
x_len = numpy.arange(len(y_acc))
plt.plot(x_len, y_vloss, &quot;o&quot;, c=&quot;red&quot;, markersize = 3) # 테스트셋
plt.plot(x_len, y_acc, &quot;o&quot;, c=&quot;blue&quot;, markersize = 3) # 학습셋

plt.show()</code></pre>
<p>keras 2.3.0 release note:<br><a href="https://velog.io/@ssongplay/Keras-KeyError-acc-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0">acc 대신 accuracy 쓴 이유</a>  </p>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/1d5324a2-ef0d-453d-a9bc-be97d6c6b140/image.png" width = 60% disply =block margin = 4>

<p>교재에는 학습셋의 정확도는 올라가지만 과적합 때문에 테스트셋의 실험 결과가 점점 나빠지게 된다고 쓰여있다. 실제로 내가 돌렸을 때에도 테스트셋 오차는 비슷한 양상을 보이고 있다. 아무래도 이 부분은 교재와 비슷하게 다시 도전해보아야 할 것 같다
  </p></p>
<h2 id="💻-학습의-자동-중단">💻 학습의 자동 중단</h2>
<pre><code class="language-python">from keras.callbacks import EarlyStopping
#학습의 자동 중단 설정, 테스트 오차가 좋지 않아도 100번 까지는 기다름
early_stopping_callback = EarlyStopping(monitor = &#39;val_loss&#39;, patience = 100)

#모델 실행
model.fit(X, Y, validation_split = 0.2, epochs = 2000, 
          batch_size = 500, callbacks = [early_stopping_callback])</code></pre>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/28d6854b-4d3d-4842-8222-5d2c55cce066/image.png" width = 60% disply =block margin = 4>

<p> epoch를 2000으로 설정했지만, 멈추는 것을 볼 수 있다. 이건 여러 번 돌려보았는데 그 때마다 횟수는 많이 차이 났다. 교재와는 숫자가 너무 많이 차이 나서 나중에 다른 데이터로도 시도해보아야겠다.
  </p></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모두의 딥러닝 13장 overfitting]]></title>
            <link>https://velog.io/@yoonie_03/%EB%AA%A8%EB%91%90%EC%9D%98-%EB%94%A5%EB%9F%AC%EB%8B%9D-13%EC%9E%A5-overfitting</link>
            <guid>https://velog.io/@yoonie_03/%EB%AA%A8%EB%91%90%EC%9D%98-%EB%94%A5%EB%9F%AC%EB%8B%9D-13%EC%9E%A5-overfitting</guid>
            <pubDate>Fri, 19 Jan 2024 14:11:37 GMT</pubDate>
            <description><![CDATA[<h2 id="💻과적합-문제">💻과적합 문제?</h2>
<pre><code class="language-python">from keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.preprocessing import LabelEncoder

import pandas as pd
import numpy as np
import tensorflow as tf

#seed 값 설정
np.random.seed(3)
tf.random.set_seed(3)

#데이터 로드
df = pd.read_csv(&#39;/content/drive/MyDrive/AI_WINTER_STUDY/sonar.csv&#39;, header = None)

#print(df.info())

#데이터
dataset = df.values
X1 = dataset[:,0:60]
Y1_obj = dataset[:,60]

#문자열 클라스를 숫자로 변환
e1 = LabelEncoder()
e1.fit(Y1_obj)
Y1 = e1.transform(Y1_obj)


#모델의 설정
model = Sequential()
model.add(Dense(24, input_dim = 60, activation = &#39;relu&#39;))
model.add(Dense(10, activation = &#39;relu&#39;)) #최종 출력 값 3개 중 하나
model.add(Dense(1, activation = &#39;sigmoid&#39;))

#모델 컴파일
model.compile(loss = &#39;binary_crossentropy&#39;,
              optimizer = &#39;adam&#39;,
              metrics = [&#39;accuracy&#39;])

#Failed to convert a NumPy array to a Tensor (Unsupported object type float).
#문제가 되는 부분의 변수 타입 바꾸기
X1 = X1.astype(np.float32)
Y1 = Y1.astype(np.float32)

#모델 실행
model.fit(X1, Y1, epochs = 200, batch_size = 5)

#결과 출력
print(&quot;\n Accuracy : %.4f&quot; %(model.evaluate(X1, Y1)[1]))</code></pre>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/f9cc3b67-21c5-439f-861e-8cc60c4defdd/image.png" width = 80% disply =block margin = 4>
정확도가 100%?
  </p>

<h2 id="📌과적합-overfitting">📌<strong>과적합</strong> overfitting</h2>
<p>모델이 학습 데이터셋 안에서는 일정 수준 이상의 예측 정확도를 보이지만, 새로운 데이터에 적용하면 잘 맞지 않은 것을 의미</p>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/a8a16bd6-6989-475c-a427-5d477fc66d88/image.png" width = 80% disply =block margin = 4>
  </p>


<p><strong>과적합이 생기는 경우</strong>
① 층(layer)이 많은 경우
② 변수가 복잡한 경우
③ 테스트셋과 학습셋이 중복될 경우</p>
<h2 id="💻과적합을-방지하려면">💻과적합을 방지하려면?</h2>
<p>학습을 위한 데이터셋과 테스트를 위한 데이터셋을 완전히 구분한 다음
학습과 동시에 테스트를 병행하며 진행할 것!</p>
<p>학습의 결과가 저장된 파일을 <strong>&#39;모델&#39;</strong>이라고 부른다. 모델을 다른 셋에 적용할 경우 학습 단계에서 각인되었던 그대로 다시 수행한다.</p>
<pre><code class="language-python">#정해진 비율만큼 학습셋과 테스트셋 구분하게 해주는 라이브러리
from sklearn.model_selection import train_test_split 

seed = 0
numpy.random.seed(seed)
tf.random.set_seed(3)

#학습셋(70%)과 테스트셋(30%) 구분
X_train, X_test, Y_train, Y_test = train_test_split(X1, Y1, test_size = 0.3, random_state=seed)

model = Sequential()
model.add(Dense(24, input_dim = 60, activation = &#39;relu&#39;))
model.add(Dense(10, activation = &#39;relu&#39;))
model.add(Dense(1, activation = &#39;sigmoid&#39;))

model.compile(loss = &#39;mean_squared_error&#39;,
              optimizer = &#39;adam&#39;,
              metrics = [&#39;accuracy&#39;])

model.fit(X_train, Y_train, epochs = 130, batch_size = 5)

#테스트셋에 모델 적용
print(&quot;\n Test Accuracy : %.4f&quot; %(model.evaluate(X_test, Y_test)[1]))</code></pre>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/ff8f1b66-c455-4aec-abf5-5f75ff7603ad/image.png" width = 80% disply =block margin = 4>
  테스트셋 실험 결과 약 80.95%의 성공률을 보인다 
</p>

<h3 id="💡검증셋validation-set">💡검증셋(Validation set)</h3>
<p>실전에서는 학습셋, 테스트셋 되의 또다른 데이터셋을 준비한다. 
이 때 훈련에 쓰이는 데이터셋을 검증셋, 마지막 테스트를 위한 데이터셋을 테스트셋이라고 부른다.
<img src="" alt=""></p>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/c4ee4ad1-76d1-48df-b9ca-de31f814bd3c/image.png" width = 80% disply =block margin = 4>
  머신러닝 개발 과정
  </p>

<p> 학습셋만 가지고 평가할 때, 층을 더하거나 에포크값을 높여 실행 횟수를 늘리면 정확도가 계속해서 올라갈 수 있다. 하지만 학습 데이터셋만으로 평가한 예측 성공률이 테스트셋에서 그대로 나타나는 것은 아니다. 학습이 깊어져서 학습셋 내부에서의 성공률이 높아지더라도 테스트셋에서 효과가 없으면 과적합이 일어나고 있다는 것이다.</p>
<p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/c20a25a5-dced-424c-bebb-d92940bbc563/image.png" width = 80% disply =block margin = 4>
  학습을 진행해도 테스트 결과가 더 이상 좋아지지 않는 지점에서 학습을 멈춰야 한다.
  </p>

<h2 id="💻모델-저장과-재사용">💻모델 저장과 재사용</h2>
<pre><code class="language-python">from keras.models import load_model #모델을 저장하는 라이브러리

model2.save(&#39;my_model.h5&#39;) #모델을 저장

del model2 #메모리 내의 모델 삭제
model2 = load_model(&#39;my_model.h5&#39;) # 모델을 새로 불러오기</code></pre>
<p>아래의 메시지가 뜨면 성공이다</p>
<pre><code class="language-md">/usr/local/lib/python3.10/dist-packages/keras/src/engine/training.py:3103: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save(&#39;my_model.keras&#39;)`.
  saving_api.save_model(</code></pre>
 <p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/0813bcff-0e35-46df-88f3-b23104e594e6/image.png" width = 80% disply =block margin = 4>
 불러온 모델을 다시 실행하면 아까와 같은 결과가 나온다
  </p>


<h2 id="📌k겹-교차-검증-k-fold-cross-validation">📌K겹 교차 검증 (k-fold cross validation)</h2>
<p>데이터셋을 여러 개로 나누어 하나씩 테스트셋으로 사용하고, 나머지를 모두 합해서 학습셋으로 사용하는 방법</p>
<p>이 방법을 이용하면 가지고 있는 데이터를 모두 테스트셋으로 사용할 수 있다.</p>
<p>5겹 교차 검증 (5-fold cross validation) 예시</p>
<h2 id="💻-k겹-교차-검증">💻 k겹 교차 검증</h2>
<pre><code class="language-python">#k겹 교차 검증 라이브러리
from sklearn.model_selection import StratifiedKFold 

# 10개의 파일로 쪼갬
n_fold = 10
skf = StratifiedKFold(n_splits = n_fold, shuffle = True, random_state = seed)

# 빈 accuracy 배열
accuracy = []

# 모델의 설정, 컴파일, 실행
for train, test in skf.split(X1, Y1):
  model3 = Sequential()
  model3.add(Dense(24, input_dim = 60, activation = &#39;relu&#39;))
  model3.add(Dense(10, activation = &#39;relu&#39;))
  model3.add(Dense(1, activation = &#39;sigmoid&#39;))
  model3.compile(loss = &#39;mean_squared_error&#39;,
                 optimizer = &#39;adam&#39;,
                 metrics = [&#39;accuracy&#39;])

  model3.fit(X1[train], Y1[train], epochs = 100, batch_size = 5)
  k_accuracy = &quot;%.4f&quot; %(model3.evaluate(X1[test], Y1[test])[1])
  accuracy.append(k_accuracy)

#결과 출력
print(&quot;\n %.f fold accuracy:&quot;% n_fold, accuracy)</code></pre>
 <p align="center"><img src ="https://velog.velcdn.com/images/yoonie_03/post/e7c75ae7-3a65-4ab7-9190-8a4b5bfc8170/image.png" width = 80% disply =block margin = 4>
 학습횟수가 늘어나다보니 평소보다 오래 걸렸다
  </p>


]]></description>
        </item>
    </channel>
</rss>