<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>do_genie.log</title>
        <link>https://velog.io/</link>
        <description>뇽안</description>
        <lastBuildDate>Sun, 26 Oct 2025 09:21:25 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>do_genie.log</title>
            <url>https://velog.velcdn.com/images/do_genie/profile/6bbc3394-e10f-40f5-b339-9a6cd89da0bc/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. do_genie.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/do_genie" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[TranAD]]></title>
            <link>https://velog.io/@do_genie/TranAD</link>
            <guid>https://velog.io/@do_genie/TranAD</guid>
            <pubDate>Sun, 26 Oct 2025 09:21:25 GMT</pubDate>
            <description><![CDATA[<h2 id="tranad-시계열-이상-탐지를-위한-딥-트랜스포머-네트워크-분석">TranAD: 시계열 이상 탐지를 위한 딥 트랜스포머 네트워크 분석</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/4c3051cf-1552-4b73-a9bb-366167769b8e/image.png" alt=""></p>
<p><strong>TranAD (Transformer-based Anomaly Detection)</strong>는 다변량 시계열 데이터(Multivariate Time Series Data)의 이상 탐지 성능을 혁신적으로 개선한 모델
트랜스포머의 강력한 <strong>어텐션(Attention)</strong> 메커니즘을 <strong>오토인코더(AutoEncoder)</strong> 구조에 통합 -&gt; <strong>적대적 학습</strong> 및 <strong>셀프-컨디셔닝</strong> 기법을 추가</p>
<h3 id="1-transformer-기반-오토인코더-구조-특징-추출과-재구성의-핵심">1. Transformer 기반 오토인코더 구조: 특징 추출과 재구성의 핵심</h3>
<p>TranAD는 입력 시계열 데이터를 효율적으로 압축하고 복원하는 오토인코더의 기본 틀을 따름</p>
<ul>
<li><p><strong>인코더 (Encoder):</strong></p>
<ul>
<li><strong>역할:</strong> 입력된 시계열 데이터 윈도우(Window)에서 <strong>장기적인 시간적 패턴</strong>과 <strong>다변수 간의 복잡한 상호 관계</strong>를 추출하여 <strong>잠재 공간(Latent Space)</strong> 벡터로 압축</li>
<li><strong>핵심:</strong> 트랜스포머의 <strong>셀프-어텐션</strong>을 사용하여, 시퀀스 내 모든 시간 단계와 변수 간의 연관성을 동시에 파악</li>
</ul>
</li>
<li><p><strong>디코더 (Decoder):</strong></p>
<ul>
<li><strong>역할:</strong> 인코더의 잠재 벡터를 다시 원래의 시계열 형태로 <strong>재구성(Reconstruct)</strong>합니다.</li>
<li><strong>특징:</strong> TranAD는 후술할 <strong>적대적 학습</strong>을 위해 특별히 <strong>두 개의 디코더(Decoder 1, Decoder 2)</strong>를 사용</li>
</ul>
</li>
</ul>
<hr>
<h3 id="2-핵심-메커니즘-모델-안정성과-이상-증폭">2. 핵심 메커니즘: 모델 안정성과 이상 증폭</h3>
<h4 id="🌟-핵심-1-셀프-컨디셔닝-self-conditioning">🌟 <strong>핵심 1: 셀프-컨디셔닝 (Self-Conditioning)</strong></h4>
<ul>
<li><p><strong>목적:</strong> 모델이 데이터의 <strong>다양한 잠재적 특징(Multi-modal Features)</strong>을 포착하고 특징 추출 능력을 강화</p>
</li>
<li><p><strong>원리:</strong> 인코더 입력에 <strong>포커스 스코어(Focus Score)</strong>라는 보조 정보를 도입</p>
<ul>
<li>이 스코어는 모델이 학습 과정에서 <strong>스스로 중요한 시간 단계나 특징</strong>에 더 많은 주의를 기울이도록 유도</li>
<li>즉, 모델이 자체적으로 가장 정보가 풍부한 부분에 집중하도록 &#39;컨디셔닝&#39;을 가하는 것입니다.</li>
</ul>
</li>
</ul>
<h4 id="⚔️-핵심-2-적대적-학습-adversarial-training">⚔️ <strong>핵심 2: 적대적 학습 (Adversarial Training)</strong></h4>
<ul>
<li><strong>목적:</strong> <strong>정상 데이터</strong>는 정확하게 재구성하고, <strong>이상 데이터</strong>는 재구성에 실패하도록(오류가 커지도록) 유도하여 <strong>이상 신호를 증폭</strong></li>
<li><strong>원리:</strong> GAN(Generative Adversarial Network) 아이디어를 차용하여 두 디코더가 경쟁적으로 학습<ul>
<li><strong>Decoder 1 (Reconstruction Decoder):</strong> 실제 입력 데이터와 재구성 결과가 유사해지도록(정상 패턴을 잘 복원하도록) 학습</li>
<li><strong>Decoder 2 (Prediction Decoder):</strong> 디코더 1의 출력과 <strong>다른 방향</strong>으로 재구성하도록 유도<ul>
<li>결과적으로, 정상 데이터에 대해서는 두 디코더의 결과가 모두 정확하지만 이상 데이터가 들어오면 이 둘의 재구성 결과가 크게 벌어지면서 <strong>이상 점수가 극대화</strong>됨</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="3-이상-탐지-anomaly-detection-과정">3. 이상 탐지 (Anomaly Detection) 과정</h3>
<p>모델 학습이 완료되면, 이상 탐지는 <strong>재구성 오류(Reconstruction Error)</strong>를 기반으로 수행</p>
<ul>
<li><strong>정상 데이터:</strong> 모델은 정상 패턴만으로 학습되었기 때문에 정상 시퀀스가 입력되면 재구성된 데이터 $\hat{X}$와 원본 데이터 $X$ 간의 차이(오류)가 <strong>작음</strong></li>
<li><strong>이상 데이터:</strong> 이상 징후를 포함한 시퀀스가 입력되면 모델이 이를 [정상]으로 재구성하지 못해 $X$와 $\hat{X}$ 간의 차이가 <strong>매우 커짐</strong></li>
<li><strong>이상 점수 (Anomaly Score):</strong> 이 재구성 오류(예: $L_1$ 또는 $L_2$ 거리)가 바로 이상 점수가 되며, 이 점수가 미리 정한 <strong>임계값(Threshold)</strong>을 초과하면 해당 시점을 최종적으로 이상(Anomaly)으로 판별</li>
</ul>
<p>$$\text{Anomaly Score} = || X - \hat{X} ||$$</p>
<p>TranAD는 이러한 독특한 구조와 학습 방식을 통해 복잡한 다변량 시계열 환경에서 <strong>빠른 속도</strong>와 <strong>높은 정확도</strong>를 모두 달성한 최신 이상 탐지 모델로 평가받고 있음</p>
<pre><code class="language-python">pip install deepod pandas numpy torch

import pandas as pd
import numpy as np
import torch
from deepod.models.time_series import TranAD
from sklearn.preprocessing import StandardScaler
from torch.utils.data import DataLoader, TensorDataset

# --- 설정 (Config) ---
FILE_PATH = &#39;your_sensor_data.csv&#39;  # 실제 파일 경로로 변경하세요
OUTPUT_PATH = &#39;tranad_anomaly_scores.csv&#39;
N_FEATURES = 10  # 센서 데이터의 개수
WINDOW_SIZE = 10  # TranAD가 고려할 시간 윈도우 크기
EPOCHS = 100
BATCH_SIZE = 128
TRAIN_RATIO = 0.8  # 학습 데이터 비율 (정상 데이터만으로 학습 가정)

# --- 1. 데이터 로드 및 전처리 함수 ---

def preprocess_data(df, window_size, train_ratio):
    # DTTM 열 분리
    dttm_col = df[&#39;DTTM&#39;]
    data = df.drop(columns=[&#39;DTTM&#39;]).values.astype(np.float32)

    # 정규화 (StandardScaler 사용)
    scaler = StandardScaler()
    data_scaled = scaler.fit_transform(data)

    # 학습 및 테스트 데이터 분할 (시간 순서대로)
    train_size = int(len(data_scaled) * train_ratio)
    train_data = data_scaled[:train_size]
    test_data = data_scaled[train_size:]
    test_dttm = dttm_col[train_size:]

    # 시퀀스(윈도우) 분할 함수
    def create_sequences(data, window):
        sequences = []
        for i in range(len(data) - window + 1):
            sequences.append(data[i:i + window])
        return np.array(sequences)

    # 데이터셋 생성
    train_sequences = create_sequences(train_data, window_size)
    test_sequences = create_sequences(test_data, window_size)

    # 윈도우 생성 후 손실로 인해 길이가 줄어든 DTTM 인덱스 맞추기
    # TranAD는 윈도우의 마지막 시점(t)에 대한 이상 점수를 출력합니다.
    test_dttm_aligned = test_dttm[window_size - 1:].reset_index(drop=True)

    return train_sequences, test_sequences, test_dttm_aligned

# --- 2. 모델 학습 및 이상치 스코어 계산 함수 ---

def run_tranad(train_seqs, test_seqs, n_features, window_size, epochs, batch_size):
    # PyTorch 장치 설정
    device = &#39;cuda&#39; if torch.cuda.is_available() else &#39;cpu&#39;

    # 파라미터 튜닝: TranAD는 &#39;seq_len&#39;과 &#39;n_features&#39;가 중요합니다.
    # 그 외 &#39;epochs&#39;, &#39;lr&#39;, &#39;batch_size&#39; 등을 튜닝할 수 있습니다.
    model = TranAD(
        seq_len=window_size,
        n_features=n_features,
        epochs=epochs,
        batch_size=batch_size,
        lr=0.001,  # 학습률 (Learning Rate) 튜닝 가능
        device=device
    )

    print(f&quot;\n--- TranAD 학습 시작 (Device: {device}) ---&quot;)
    # 학습: TranAD는 비지도 학습이므로 X_train만 사용
    model.fit(train_seqs)

    print(&quot;--- TranAD 테스트 시작 ---&quot;)
    # 예측: 테스트 데이터에 대한 이상치 스코어 계산
    # &#39;score_t&#39;는 시점(time point)별 이상치 스코어입니다.
    # scores_t의 길이는 test_seqs의 길이와 같습니다.
    scores = model.predict(test_seqs, return_score=True)
    anomaly_scores_t = scores[&#39;score_t&#39;]

    return anomaly_scores_t

# --- 메인 실행 ---
if __name__ == &#39;__main__&#39;:
    # 1. 데이터 로드 (DTTM, Sensor1, Sensor2, ..., Sensor10)
    try:
        df = pd.read_csv(FILE_PATH)
        if &#39;DTTM&#39; not in df.columns:
            raise ValueError(&quot;CSV 파일에 &#39;DTTM&#39; 열이 포함되어 있어야 합니다.&quot;)

        # 데이터의 형태를 확인합니다.
        print(f&quot;원본 데이터 크기: {df.shape}&quot;)

    except FileNotFoundError:
        print(f&quot;오류: 파일을 찾을 수 없습니다. 경로를 확인하세요: {FILE_PATH}&quot;)
        # 예시 데이터프레임 생성 (테스트용)
        # 실제 데이터를 사용하는 경우 이 부분을 주석 처리하고 위의 FILE_PATH를 수정하세요.
        time_steps = 1000
        df = pd.DataFrame({
            &#39;DTTM&#39;: pd.to_datetime(pd.Series(range(time_steps)).apply(lambda x: f&#39;2024-01-01 00:00:{x:02}&#39;)),
            **{f&#39;Sensor{i}&#39;: np.sin(np.linspace(0, 10, time_steps)) + np.random.normal(0, 0.1, time_steps) + i for i in range(1, N_FEATURES + 1)}
        })
        # 인위적인 이상치 주입 (테스트용)
        df.loc[800:810, &#39;Sensor1&#39;] += 10
        print(&quot;예시 데이터를 생성하여 사용합니다.&quot;)


    # 2. 데이터 전처리
    train_sequences, test_sequences, test_dttm_aligned = preprocess_data(df, WINDOW_SIZE, TRAIN_RATIO)

    print(f&quot;학습 시퀀스 크기: {train_sequences.shape}&quot;)
    print(f&quot;테스트 시퀀스 크기: {test_sequences.shape}&quot;)
    print(f&quot;정렬된 DTTM 크기: {test_dttm_aligned.shape}&quot;)


    # 3. TranAD 모델 학습 및 스코어 계산
    anomaly_scores_t = run_tranad(
        train_sequences, 
        test_sequences, 
        N_FEATURES, 
        WINDOW_SIZE, 
        EPOCHS, 
        BATCH_SIZE
    )

    # 4. 결과물 생성 및 저장

    # 초당(Row 단위) 스코어를 DataFrame으로 변환
    results_df = pd.DataFrame({
        &#39;DTTM&#39;: test_dttm_aligned,
        &#39;Anomaly_Score&#39;: anomaly_scores_t.flatten()  # 스코어는 1차원 벡터
    })

    # 스코어가 높을수록 이상치일 확률이 높습니다.
    results_df.to_csv(OUTPUT_PATH, index=False)

    print(f&quot;\n--- 완료 ---&quot;)
    print(f&quot;이상치 스코어가 &#39;{OUTPUT_PATH}&#39; 파일에 저장되었습니다.&quot;)
    print(f&quot;저장된 결과 크기: {results_df.shape}&quot;)
</code></pre>
<table>
<thead>
<tr>
<th>변수</th>
<th align="left">설명</th>
<th align="center">중요도</th>
</tr>
</thead>
<tbody><tr>
<td>FILE_PATH</td>
<td align="left">분석할 센서 데이터 CSV 파일 경로</td>
<td align="center">높음</td>
</tr>
<tr>
<td>OUTPUT_PATH</td>
<td align="left">이상치 스코어를 저장할 CSV 파일 경로</td>
<td align="center">중간</td>
</tr>
<tr>
<td>N_FEATURES</td>
<td align="left">센서 데이터(DTTM 제외)의 개수 (열 개수)</td>
<td align="center">높음</td>
</tr>
<tr>
<td>WINDOW_SIZE</td>
<td align="left">TranAD가 이상 판단을 위해 참고할 시간 길이 (W)</td>
<td align="center">매우 높음 (튜닝 요소)</td>
</tr>
<tr>
<td>TRAIN_RATIO</td>
<td align="left">학습 데이터로 사용할 데이터의 비율 (0.8 = 80%)</td>
<td align="center">중간</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer의 기본 구조]]></title>
            <link>https://velog.io/@do_genie/Transformer%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@do_genie/Transformer%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Sun, 26 Oct 2025 08:10:41 GMT</pubDate>
            <description><![CDATA[<p>트랜스포머의 기본 구조는 <strong>인코더(Encoder)</strong>와 <strong>디코더(Decoder)</strong>라는 두 가지 핵심 블록을 여러 개 쌓아 올린 형태
<img src="https://velog.velcdn.com/images/do_genie/post/158f9dac-a3e0-404f-9d53-3f2a5353f6da/image.png" alt=""></p>
<h3 id="1-전처리-과정">1. 전처리 과정</h3>
<p>입력 계층인코더와 디코더에 데이터가 들어가기 전에, 두 가지 중요한 전처리 과정이 수행</p>
<ul>
<li><strong>입력 임베딩 (Input Embedding)</strong>: 단어(토큰)를 모델이 처리할 수 있는 고차원 벡터로 변환</li>
<li><strong>위치 인코딩 (Positional Encoding)</strong>: 트랜스포머는 RNN과 달리 순차적으로 데이터를 처리하지 않고 병렬 처리하기 때문에, 시퀀스 내의 단어 순서 정보를 알지 못함.<ul>
<li>이 문제를 해결하기 위해, 각 토큰의 위치 정보를 담은 벡터를 입력 임베딩 벡터에 더함 (주로 사인 및 코사인 함수를 사용하여 구현)</li>
</ul>
</li>
</ul>
<h3 id="2-인코더-encoder-블록">2. 인코더 (Encoder) 블록</h3>
<p>인코더는 입력 시퀀스를 처리하고 그 의미를 추출하여 문맥을 이해하는 역할
여러 개의 동일한 인코더 블록이 쌓여 있음(논문에서는 6개)
<strong>각 인코더 블록은 두 개의 서브 레이어로 구성됨.</strong></p>
<p><strong>1. 멀티-헤드 셀프-어텐션 (Multi-Head Self-Attention)역할:</strong> </p>
<ul>
<li>입력 문장 내의 모든 단어들 간의 관계를 동시에 파악합니다.</li>
<li>원리: 각 단어는 문장 내 다른 단어들과의 중요도를 계산하여 자신의 표현을 업데이트합니다. 이를 통해 모델은 문장의 문맥을 효과적으로 포착할 수 있습니다. </li>
</ul>
<p><strong>2. 피드 포워드 네트워크 (Feed-Forward Network, FFN)역할:</strong>
어텐션 레이어의 출력을 받아 비선형적 변환을 수행하여 특징 표현을 강화합니다.</p>
<ul>
<li>구조: 선형 계층 $\to$ ReLU $\to$ 선형 계층의 간단한 MLP 구조</li>
<li>추가 구성 요소: 각 서브 레이어의 출력은 <strong>잔차 연결(Residual Connection)</strong>을 거친 후 <strong>층 정규화(Layer Normalization)</strong>가 적용</li>
</ul>
<h3 id="3-디코더-decoder-블록">3. 디코더 (Decoder) 블록</h3>
<p>디코더는 인코더의 출력을 바탕으로 <strong>출력 시퀀스(번역문, 답변 등)</strong>를 생성하는 역할
인코더와 마찬가지로 여러 개의 동일한 디코더 블록이 쌓여 있음 (논문에서는 6개)
<strong>각 디코더 블록은 세 개의 서브 레이어로 구성</strong></p>
<p><strong>1. 마스크드 멀티-헤드 셀프-어텐션 (Masked Multi-Head Self-Attention)역할:</strong>
출력 단어를 순차적으로 생성할 때, 현재 시점의 단어가 <strong>미래의 단어(아직 생성되지 않은 단어)</strong>를 참고하지 못하도록 <strong>마스킹(Masking)</strong></p>
<ul>
<li>원리: 이전 시점까지 생성된 단어들만을 참고하여 다음 단어를 예측하도록 함</li>
</ul>
<p><strong>2. 인코더-디코더 어텐션 (Encoder-Decoder Attention, Cross-Attention)역할:</strong>
디코더의 현재 상태(Query)와 인코더의 최종 출력(Key, Value) 간의 관계를 파악</p>
<ul>
<li>원리: 현재 출력해야 할 단어가 입력 문장(소스 문장)의 어떤 부분과 가장 관련이 있는지 집중(Attention)하여 정보를 추출</li>
</ul>
<p><strong>3. 피드 포워드 네트워크 (Feed-Forward Network, FFN)</strong>
인코더와 동일하게 비선형 변환 및 특징 강화를 수행</p>
<h4 id="4-최종-출력-계층">4. 최종 출력 계층</h4>
<p>디코더 스택의 마지막 출력은 <strong>선형 계층(Linear Layer)</strong>과 소프트맥스(Softmax) 함수를 거쳐 모델의 전체 어휘 집합에 대한 다음 단어의 확률 분포로 변환 </p>
<ul>
<li>이 중 가장 높은 확률을 가진 단어가 최종 출력으로 선택</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer - Multilayer Perceptron(MLP)]]></title>
            <link>https://velog.io/@do_genie/Transformer-Multilayer-PerceptronMLP</link>
            <guid>https://velog.io/@do_genie/Transformer-Multilayer-PerceptronMLP</guid>
            <pubDate>Sun, 26 Oct 2025 07:57:53 GMT</pubDate>
            <description><![CDATA[<h2 id="transformer의-기본-구조">Transformer의 기본 구조</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/3aa15a1e-16fe-4207-866e-9363da633ec8/image.png" alt=""></p>
<p><strong>Attention block</strong></p>
<ul>
<li>모든 단어는 고차원 공간에 임베딩 되어 있음 ! </li>
<li>각 단어들은 Attention 블록을 거치면서 다양한 문맥을 가질 수 있도록 업데이트 됨</li>
</ul>
<p><strong>MLP</strong></p>
<ul>
<li>어떤 사실 정보를 저장하기에는 MLP쪽이 더 많은 정보를 가지고 있음</li>
</ul>
<h2 id="mlp의-기본-전제">MLP의 기본 전제</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/ec329383-a3a2-4191-9e5f-c8be8dc977f0/image.png" alt=""></p>
<ul>
<li>각 임베딩 데이터들이 MLP 블록 안으로 들어오게 된다</li>
<li>그리고 각 단어들은 각각 고유한 벡터를 가지고 있음</li>
</ul>
<p>MLP의 역할은?</p>
<ul>
<li>각 벡터의 값들을 미리 정한 연산 순서대로 계산해줌</li>
<li>최종적인 결과 벡터를 얻게 됨</li>
<li>이 결과 벡터는 처음 input으로 넣은 벡터와 더해져서 다음 레이어로 넘어가게 됨
<img src="https://velog.velcdn.com/images/do_genie/post/86b94801-fdca-4970-a0fe-fcc83095edf0/image.png" alt="">
<img src="https://velog.velcdn.com/images/do_genie/post/c835550a-ee5f-44d0-a70c-8741298b2eee/image.png" alt="">
이 과정을 모든 벡터에 대해 똑같이 수행, 병렬적 적용 (독립적 연산)
<img src="https://velog.velcdn.com/images/do_genie/post/d161d129-2a98-4298-bbc4-c58745b33e6f/image.png" alt=""><h4 id="1-첫-번째-선형-계층-first-linear-layer">1. 첫 번째 선형 계층 (First Linear Layer)</h4>
</li>
<li>구조 : $x W_1 + b_1$</li>
<li>역할 : 입력 벡터의 차원($d_{\text{model}}$ 또는 $d_{\text{embed}}$)을 <strong>확장(Expansion)</strong><ul>
<li>트랜스포머의 오리지널 논문(&quot;Attention Is All You Need&quot;)에서는 입력 차원 $d_{\text{model}}=512$를 4배 확장하여 $d_{\text{ff}}=2048$ 차원으로 만듬</li>
</ul>
</li>
<li>목적 : 고차원 공간으로 매핑함으로써 모델이 <strong>더 복잡한 특징(feature)</strong>과 비선형적 관계를 학습할 수 있는 능력을 부여합니다.</li>
</ul>
<h4 id="2-활성화-함수-relu-activation">2. 활성화 함수 (ReLU Activation)</h4>
<ul>
<li>구조:  $\max(0, \cdot)$</li>
<li>역할: <strong>비선형성(Non-linearity)</strong>을 도입</li>
<li>목적: 선형 변환만으로는 복잡한 데이터 패턴을 학습할 수 없기 때문에, ReLU(Rectified Linear Unit) 함수를 통해 모델에 비선형성을 추가하여 표현력을 극대화</li>
</ul>
<h4 id="3-두-번째-선형-계층-second-linear-layer">3. 두 번째 선형 계층 (Second Linear Layer)</h4>
<ul>
<li>구조: $\cdot W_2 + b_2$</li>
<li>역할: 확장된 차원($d_{\text{ff}}=2048$)을 다시 원래의 차원($d_{\text{model}}=512$)으로 <strong>축소(Projection)</strong></li>
<li>목적: 확장된 특징을 압축 -&gt; 변환된 정보를 다음 서브 레이어나 최종 출력 계층으로 전달하기 위해 차원을 일치시킴</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer - Attention]]></title>
            <link>https://velog.io/@do_genie/Transformer-Attention</link>
            <guid>https://velog.io/@do_genie/Transformer-Attention</guid>
            <pubDate>Sun, 26 Oct 2025 07:35:53 GMT</pubDate>
            <description><![CDATA[<h3 id="attention-메커니즘">attention 메커니즘</h3>
<ul>
<li>문맥에 따라 단어는 각각 다른 의미를 가지게 됨</li>
</ul>
<ol>
<li>각 단어를 임베딩 스페이스로 보냄 (각 단어는 각각 문맥적인 의미는 갖지 않음)</li>
<li>임베딩 스페이스로 옮긴 뒤, 각각의 문맥적인 의미를 파악하게 됨<ul>
<li>문맥을 통해 단어 A를 실제 의미로 어디로 얼마나 움직여야 하는지 파악!
<img src="https://velog.velcdn.com/images/do_genie/post/65aca4a0-5301-4662-a975-811b1b7f949f/image.png" alt=""></li>
</ul>
</li>
<li>모든 벡터가 네트워크를 통해서 여러 Attention 블록을 거침 </li>
<li>최종적으로 마지막 단어를 예측하는건 마지막 벡터 (Output)</li>
</ol>
<h3 id="attention의-쿼리">Attention의 쿼리</h3>
<p><img src="https://velog.velcdn.com/images/do_genie/post/875c6517-8bd4-47f3-bf98-8c8a345697d0/image.png" alt="">
<strong>Query Vector</strong></p>
<ul>
<li>질문이 쿼리라는 다른 벡터로 인코딩 되어 질문한다고 생각하면 됨</li>
<li>쿼리벡터는 임베딩벡터보다 차원이 조금 작음(128차원)</li>
<li>모든 토큰(E)에 W_Q를 곱해서 쿼리벡터(Q)를 생성함</li>
<li>W는 가중치, 임베딩스페이스에 있는 단어 토큰을 쿼리 스페이스로 매핑하는 역할
  <img src="https://velog.velcdn.com/images/do_genie/post/910fdff4-21f3-4244-8195-cc8861295407/image.png" alt=""></li>
</ul>
<p><strong>Key Vector</strong></p>
<ul>
<li>질문(Q)에 대한 답을 찾는 도구 역할을 하는 벡터</li>
<li>훈련 가능한 파라미터(W_K)로 이루어져 있고, 임베딩 스페이스에 있는 단어 토큰을 키 스페이스로 매핑하는 역할을 함
  <img src="https://velog.velcdn.com/images/do_genie/post/000d894a-acb1-484a-996f-1df4b0ed32fa/image.png" alt="">
  <img src="https://velog.velcdn.com/images/do_genie/post/01b253de-702b-42d5-8eb8-d57ddd5e939c/image.png" alt=""></li>
<li>쿼리와 키의 벡터가 비슷할 때 둘이 일치한다고 볼 수 있음<ul>
<li>각 키가 각 쿼리랑 얼마나 비슷한지 (잘 맞는지) 확인하기 위해 내적을 확인함
<img src="https://velog.velcdn.com/images/do_genie/post/44c3af8e-81fe-4acb-87b4-1b936f08d7c6/image.png" alt=""><ul>
<li>여기서 이 맵을 Attention Map이라고 한다.</li>
</ul>
</li>
<li>내적이 클수록 비슷하다고 볼 수 있음(원의 크기)</li>
<li>fluffy, blue는 creature와 비슷한 위치에 있음을 알 수 있음 (형용사)</li>
<li>이 점수를 가지고 열에 대해서 가중치를 구해 합계를 구할 수 있음!! </li>
<li>이 가중치가 0~1까지 확률 분포로 나타났음 좋겠다 -&gt; softmax 함수를 통해 확률분포로 변환! 
<img src="https://velog.velcdn.com/images/do_genie/post/4771b3e6-b6e4-42e8-b663-44a58d913c4c/image.png" alt=""></li>
<li>다음과 같이 식으로 정리할 수 있음
<img src="https://velog.velcdn.com/images/do_genie/post/a31defe7-0951-48d0-9fea-aa471bfde23b/image.png" alt=""></li>
</ul>
</li>
</ul>
<p><strong>Transformer를 훈련할 때 병렬적으로 훈련한다.</strong>
하나의 문장에서 여러개의 훈련 데이터를 만들 때 뒤에 오는 토큰이 앞에 오는 토큰에 영향을 주지 않게 하기 위해 병렬적 훈련을 진행한다.</p>
<ul>
<li>이 과정을 마스킹이라고 함
![](<a href="https://velog.velcdn.com/images/do_genie/post/a15f4217-210a-4156-a9cb-c7fba8098e0b/image.pn">https://velog.velcdn.com/images/do_genie/post/a15f4217-210a-4156-a9cb-c7fba8098e0b/image.pn</a> g)</li>
</ul>
<p><strong>Value Vector</strong>
<img src="https://velog.velcdn.com/images/do_genie/post/35b9bcef-4171-4b4a-9587-0acfc738e8ba/image.png" alt=""></p>
<ul>
<li>value vector에 fluffy라는 단어를 곱해줌 -&gt; 이 결과를 value라고 한다.</li>
<li>이후에 뒤에 오는 단어에 value를 더해주면 creature라는 단어의 의미가 변하게 됨!</li>
<li>더 앞에 있는 단어의 value를 다시 creature라는 단어에 더 더해주면 의미가 또 변하게 됨!
<img src="https://velog.velcdn.com/images/do_genie/post/78e6f423-73c2-491a-a0bd-6c41574b81c4/image.png" alt=""></li>
<li>key값은 지금 fluffy와 blue에 가중치가 더 높게 나옴 -&gt; 이 때 이 값들에 W_V(value Matrix)를 곱하고 더해주면 E의 변화량이 나오게 됨</li>
<li>원래 있던 E값에 이 변화량을 더해주면 새로운 의미가 변화된 creature가 나오게 된다.</li>
<li>이걸 모든 임베딩 벡터에 대해서 전부 계산하면 Attention block을 통과하면 의미를 더 잘 담은 문장이 나오게 됨 -&gt; 단일 헤드 어텐션이라고 부른다.</li>
</ul>
<h2 id="최종-파라미터-가중치-매트릭스">최종 파라미터 (가중치 매트릭스)</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/14d12593-46c5-4151-8336-2cf8659f9e5d/image.png" alt=""></p>
<h2 id="멀티-헤드-어텐션">멀티 헤드 어텐션</h2>
<p>하나의 value matrix를 사용하는 것이 아니고, 전체 행렬을 2개로 쪼갠 다음 여러 의미의 방향을 선형적으로 더한 것
<img src="https://velog.velcdn.com/images/do_genie/post/5ce17893-ca81-4de3-9107-c03b7822b8d7/image.png" alt=""></p>
<ul>
<li>여러 개의 병렬 작업을 동시에 수행 (어텐션 헤드가 여러 개)</li>
<li>N개의 서로 다른 키와 쿼리, N개의 서로 다른 어텐션 패턴, 어텐션 맵이 생성된다는 뜻</li>
<li>각각의 헤드는 고유 Value Matrix가 있고, 고유 Value sequence를 가지고 있음</li>
<li>각각의 어텐션 맵에 따라 가중치로 곱해지게 됨
  <img src="https://velog.velcdn.com/images/do_genie/post/39be0725-1eb4-4380-b737-1a76c9a3217f/image.png" alt=""></li>
<li>이 방향을 전부 더해서 결과를 원래 임베딩(단어)에 더해주는 것</li>
<li>다양한 방법을 통해 문맥에 따라 의미가 어떻게 달라지는지를 알게 되는 것</li>
</ul>
<h2 id="cross-attention">Cross Attention</h2>
<ul>
<li>두개의 다른 데이터로 처리할 때 사용</li>
<li>다른 언어로 번역할때, 음성을 문자로 변형할 때 등등</li>
</ul>
<p><strong>Self Attention과 다른 점</strong>
키와 쿼리를 곱하는 매트릭스에서 각각 다른 언어를 곱한다는 점이 차이점
<img src="https://velog.velcdn.com/images/do_genie/post/9c0c71d2-e83d-4c91-af01-f52d764406c9/image.png" alt=""></p>
<ul>
<li>각각의 단어가 어떤 단어에 대응되는지를 확인함</li>
<li>이 때 마스킹 하지 않음 (다른 단어가 앞 단어에 영향을 주는 경우가 없음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[GPT - Transformer 로직 흐름]]></title>
            <link>https://velog.io/@do_genie/GPT-Transformer-%EB%A1%9C%EC%A7%81-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@do_genie/GPT-Transformer-%EB%A1%9C%EC%A7%81-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Sat, 25 Oct 2025 07:03:45 GMT</pubDate>
            <description><![CDATA[<h2 id="토큰이란">토큰이란?</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/8641244f-e62c-4843-ab01-5d7b52903c66/image.png" alt=""></p>
<p>데이터의 가장 작은 단위를 벡터화 한 것으로 이해하면 쉬움
<img src="https://velog.velcdn.com/images/do_genie/post/78720707-d407-487b-80a6-9eb2d1ee6139/image.png" alt="">
의미가 비슷한 단어들은 상대적으로 비슷한 위치에 있을 수 있음</p>
<h2 id="embedding">Embedding</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/16420927-0938-41f3-925b-7f19ab7657ce/image.png" alt="">
학습 가능한 매개변수 (Weight)로 단어 벡터간의 연산을 진행해 output을 도출한다.
<img src="https://velog.velcdn.com/images/do_genie/post/97b5dd6e-dcc2-4d90-b4bb-9dd4b1f23bf7/image.png" alt="">
이때 비슷한 단어끼리는 양수, 서로 다른 의미를 가진 단어끼리는 음수의 값을 가지게 됨</p>
<ul>
<li>이 입력 데이터는 일차원일수도 있고, 고차원 Tensor일 수 있음</li>
</ul>
<h2 id="attention">Attention</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/3ba79eb6-3cda-439a-9e9b-b1fefacc27ec/image.png" alt="">
이렇게 각 열(토큰)의 벡터들은 서로 연산하며 의미를 업데이트하게 됨 -&gt; 벡터 값 업데이트
ex) 동음이의어 등..
여기서의 의미는 특정한 벡터로 인코딩하는 것과 동일한 의미</p>
<h2 id="multilayer-perceptron">Multilayer Perceptron</h2>
<p><img src="https://velog.velcdn.com/images/do_genie/post/5212e020-f187-4f0f-9e9e-74d55b6335d2/image.png" alt="">
Multilayer Perceptron을 통해서 병렬로(같은 벡터 끼리만) 추가적인 연산을 진행해 값을 업데이트 하게 됨
-&gt; 각 벡터가 어떤 역할을 하는지에 대한 연산을 진행함</p>
<p>그리고 레이어 사이사이에 정규화 진행!</p>
<ul>
<li>Softmax 함수 사용해서 각 단어의 확률 분포로 나타낼 수 있도록 함
<img src="https://velog.velcdn.com/images/do_genie/post/45fdfd19-8250-4034-b871-a4f9d6c2a6ab/image.png" alt="">
<img src="https://velog.velcdn.com/images/do_genie/post/a6bdfdf8-760e-4790-bb77-8ebe65a6ade3/image.png" alt="">
이때 Temperature 라는 T 변수를 조정하며 어느정도로 균일한 확률을 보일 건지 정해줌</li>
<li>T가 클수록 : 데이터의 확률이 균등하게 조정됨 (뒤에 어떤 단어가 올 지 더 많은 가능성 부여)</li>
<li>T가 작을수록 : 가장 높은 확률을 보이는 단어의 확률이 1에 가까워짐 (하나만 선택될 확률 증가)</li>
</ul>
<h1 id="기본-로직">기본 로직</h1>
<ol>
<li>처음 임베딩 매트릭스 (기본 정의 매트릭스)를 통해서 단어의 벡터를 그대로 가져옴</li>
<li>Attention 과정을 거쳐 단어의 의미를 업데이트 (맥락정보 업데이트)<ul>
<li>이 때 Context size를 통해서 모델이 처리할 수 있는 맥락 참고 텍스트 사이즈를 정해줘야 함</li>
</ul>
</li>
<li>Multilayer Perceptron을 통해서 추가적인 연산 진행해줌 (병렬 처리)</li>
<li>마지막에 올 단어를 예측하기 위해서 필요한 것은 각 단어의 확률 분포 (높은 확률을 갖는 단어가 등장해야 함)<ul>
<li>이 때 , 확률 분포로 정규화 하기 위해 Softmax 함수 사용</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 먼징 : 문자열 다루기, 정규표현식, 데이터 정리]]></title>
            <link>https://velog.io/@do_genie/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A8%BC%EC%A7%95-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@do_genie/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A8%BC%EC%A7%95-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 05 Apr 2024 09:01:38 GMT</pubDate>
            <description><![CDATA[<h2 id="상태가-안좋은-데이터">상태가 안좋은 데이터?</h2>
<ol>
<li><p>데이터 형식 문제</p>
<ul>
<li>영어 대소문자가 엉망</li>
<li>무의미한 공백이 있는 데이터</li>
</ul>
</li>
<li><p>실제 데이터에 문제가 있는 경우</p>
<ul>
<li>중복<ul>
<li>특수하거나 예외적인 값이 존재</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="데이터를-전처리-하기-전에">데이터를 전처리 하기 전에</h2>
<blockquote>
</blockquote>
<ul>
<li>문자열 데이터를 사용한다면 데이터를 열어 직접 확인하라</li>
<li>설명서가 있다면 꼭 읽어라</li>
<li>다양한 데이터에 적용 가능한 공통 질문 목록을 만들어라</li>
<li>이미 정답을 아는 값을 직접 추출해 정답과 비교하라</li>
</ul>
<br>

<h2 id="데이터-자체의-문제가-있는-경우-해결하는-법">데이터 자체의 문제가 있는 경우 해결하는 법</h2>
<ol>
<li><p><strong>중복 데이터</strong>
중복데이터를 하나의 표본으로 간주하는 경우, 중복 데이터를 하나로 병합하는 경우가 있음</p>
</li>
<li><p><strong>같은 의미의 값이 여러 개 존재</strong>
중복데이터와 조금 다르다. 데이터를 갱신하며 오래된 값과 새 값을 같이 저장하며 일어나게 되는 문제.(일부 데이터를 여러 번 사용하게 되면 기록이 여러번 남을 수 있다.)
예를 들어, 공장에서 문제가 있는 부품을 고쳐 재활용 하면 기존 식별자를 그대로 사용하게 된다.</p>
<blockquote>
</blockquote>
<p>식별자1 -&gt; 고장
식별자1 -&gt; 정상 작동</p>
</li>
<li><p><strong>데이터 누락</strong>
이럴 때는 비어있는 데이터를 그냥 둘지, 특정 값으로 채울지를 결정해야 한다. </p>
</li>
<li><p><strong>NULL 값</strong>
다른 데이터를 보고 값을 추정하고나, NULL이 아닌 표본의 평균을 사용하는 방법 등이 있다. 
수집과정에서 누락된 데이터가 NULL로 채워져 있기도 하다. 상황에 따라 NULL값의 여부 자체를 특징 값으로 활용할 수 있다.</p>
</li>
<li><p><strong>이상치</strong>
이상치 자체를 데이터에서 완전히 배제하는 경우 
데이터 누락때문에 이상치가 생기는 경우-&gt; NULL값을 사용하거나, 미리 정해놓은 값을 NULL값 대신 사용하기</p>
</li>
<li><p><strong>오래된 데이터</strong>
필요에 따라 너무 오래된 데이터는 걸러내고 사용한다.</p>
</li>
<li><p><strong>인공 데이터</strong>
인공 데이터란 실제로 존재하는 값을 측정한게 아니고, 사람이 만든 데이터.
시스템 시험용으로 만든 데이터.</p>
</li>
<li><p><strong>불규칙한 데이터 수집</strong>
보통의 데이터는 일정한 간격으로 수집한다. 따라서 일정한 간격이 아니라면 문제가 발생한다.
내삽법으로 간격을 일정하게 바꾸어 주기도 한다. 
같은 시각에 다른 데이터가 기록되어 있는 경우도 있다. -&gt; 이 경우 시각을 기록하는 정밀도가 너무 낮기 때문에 발생하는 문제</p>
<blockquote>
<p>ex) 시각을 분단위로 기록하며 측정을 초단위로 한다면 서로 다른 데이터가 같은 시각에 기록된 것 처럼 보일 수 있음!</p>
</blockquote>
</li>
</ol>
<h2 id="데이터-형식-문제인-경우-해결하는-법">데이터 형식 문제인 경우 해결하는 법</h2>
<ol>
<li><p><strong>표 또는 열마다 다른 형식을 사용한 경우</strong>
호환성에 주의하며 데이터 셋을 병합한다.</p>
</li>
<li><p><strong>공백문자</strong>
파이썬에서는 strip()이라는 메서드로 문자열 앞뒤 공백문자를 제거한다.</p>
</li>
<li><p><strong>불규칙한 대소문자 사용</strong>
파이썬에서는 lower()과 upper()메서드를 사용할 수 있다.</p>
</li>
<li><p><strong>불규칙한 구분 기호</strong>
열을 나누는 기준이 되는 구분 기호는 통일해서 사용해야 한다.</p>
<blockquote>
<p>콤마( , ), 탭(\t) , 파이프( | )</p>
</blockquote>
</li>
<li><p><strong>불규칙한 NULL문자</strong>
NA, unavailable, unknown 등으로 표현된 경우가 있음 ! 통일해서 사용하기</p>
</li>
<li><p><strong>유효하지 않은 문자 사용</strong>
인코딩 문제로 글자가 깨지는 경우 있음. 이 경우 걸러낸다.</p>
<pre><code>s.decode(&quot;asci&quot;, &quot;ignore&quot;) #아스키 기준에 적합하지 않은 경우는 무시하기</code></pre></li>
<li><p><strong>불규칙한 날짜 및 시간 표기</strong>
파이썬 dateutil 사용해 걸러내기</p>
<pre><code>import deteutil.parser as p
p.parse(&quot;August 13, 1985&quot;)</code></pre></li>
</ol>
<ul>
<li>만일 시간 정보가 없다면 0시</li>
</ul>
<ol start="8">
<li>** 운영체제 호환문제 **
맥OS -&gt; \n
윈도우 -&gt; \r\n<br>
<br>



</li>
</ol>
<h2 id="정규표현식">정규표현식</h2>
<table>
<thead>
<tr>
<th align="center">패턴유형</th>
<th align="center">정규식</th>
<th align="center">참고</th>
</tr>
</thead>
<tbody><tr>
<td align="center">문자열</td>
<td align="center">abc123</td>
<td align="center">abc123을 찾기</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">문자 반복</td>
<td align="center">a*b</td>
<td align="center">*앞의 문자열이 반복된다고 가정하고(0회 포함) 반복되는 모든 문자를 가져온다.</td>
</tr>
<tr>
<td align="center">최소 1회 이상 문자 반복</td>
<td align="center">a+b</td>
<td align="center">+앞의 문자가 최소 1회 이상 반복하는 경우 문자 가져옴</td>
</tr>
<tr>
<td align="center">최대 1회 이하 문자 반복</td>
<td align="center">a?b</td>
<td align="center">?앞의 문자가 0회 혹은 1회 반복되는 경우 문자 가져옴</td>
</tr>
<tr>
<td align="center">정해진 횟수만큼 문자 반복</td>
<td align="center">a{5}</td>
<td align="center">aaaaa 찾기</td>
</tr>
<tr>
<td align="center">정해진 횟수만큼 특정 패턴 반복</td>
<td align="center">(a*b){3}</td>
<td align="center">a가 반복(0회 포함)되는 ab 문자를 3번 반복하는 문자 출력</td>
</tr>
<tr>
<td align="center">특정 패턴 반복, 반복횟수 범위로 정의</td>
<td align="center">a{2, 4}</td>
<td align="center">2, 3, 4회 a를 반복</td>
</tr>
<tr>
<td align="center">정해진 문자 후보 중 1개 등장</td>
<td align="center">[a,b]c</td>
<td align="center">대괄호 내부의 문자열 중 하나가 나타나면 됨</td>
</tr>
<tr>
<td align="center">[]와 *의 조합</td>
<td align="center">[ab]*c</td>
<td align="center">*가 []에 적용되어 대괄호 내부 문자열중 하나가 임의 횟수만큼 반복</td>
</tr>
<tr>
<td align="center">가능한 문자 후보를 범위로</td>
<td align="center">[A-H][a-z]</td>
<td align="center">a<del>h, A</del>H까지 허용</td>
</tr>
<tr>
<td align="center">제외할 문자 정의</td>
<td align="center">[^AB]</td>
<td align="center">대괄호 내 문자만 아니면 됨</td>
</tr>
<tr>
<td align="center">문자열 후보 제시</td>
<td align="center">Dr|Mr|Ms|Mrs</td>
<td align="center">주어진 문자열 중 하나면 됨</td>
</tr>
<tr>
<td align="center">괄호, |, *를 조합한 예시</td>
<td align="center">([A-Z]|[a-z])*</td>
<td align="center">알파벳 대문자 혹은 소문자로 이루어진 모든 문자</td>
</tr>
<tr>
<td align="center">행의 시작 부분 탐색</td>
<td align="center">^ab</td>
<td align="center">ab로 시작하는 모든 행</td>
</tr>
<tr>
<td align="center">행의 종료 부분 탐색</td>
<td align="center">ab$</td>
<td align="center">ab로 끝나는 모든 행</td>
</tr>
<tr>
<td align="center">특수문자</td>
<td align="center">\[</td>
<td align="center">&quot;[&quot; 찾기</td>
</tr>
<tr>
<td align="center">개행문자를 제외한 모든 문자열</td>
<td align="center">.</td>
<td align="center">a, *, _, .</td>
</tr>
<tr>
<td align="center">비탐욕적 탐색</td>
<td align="center">&lt;.*&gt;?</td>
<td align="center">&lt;&gt;로 둘러싼 모든 문자열중 짧은 것을 찾음</td>
</tr>
<tr>
<td align="center">빈칸</td>
<td align="center">\s</td>
<td align="center">공백, 탭, 개행문자 찾음</td>
</tr>
</tbody></table>
<pre><code>import re

# 0~9로 시작 + 빈칸 + A~Z로 시작하거나, a~z로 시작하는 문자가 0회 이상 반복되는 경우
# 1600 pennsylvania를 찾을 수있음
pattern = r&quot;^[0-9]\s[A-Z][a-z]*&quot; </code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Data Science 큰 그림]]></title>
            <link>https://velog.io/@do_genie/Data-Science-%ED%81%B0-%EA%B7%B8%EB%A6%BC</link>
            <guid>https://velog.io/@do_genie/Data-Science-%ED%81%B0-%EA%B7%B8%EB%A6%BC</guid>
            <pubDate>Fri, 05 Apr 2024 08:10:04 GMT</pubDate>
            <description><![CDATA[<p>데이터 과학의 로드맵은 다음과 같다.
<img src="https://velog.velcdn.com/images/do_genie/post/a38d29e8-1726-46ef-9e08-9833e08ef4e9/image.png" alt=""></p>
<ol>
<li>모델 수립 및 분석 단계에 있다가도 문제 파악 단계로 옮겨갈 수 있다.<ul>
<li>지금 푸는 문제가 잘 정의된 실제로 의미있는 문제인지 계속 고민해야 한다.<br></li>
</ul>
</li>
<li>결과정리 및 발표와 코드 배포 두가지 방법으로 나뉠 수 있다.<ul>
<li>둘다 하는 경우도 있다!</li>
<li>최종 목적이 무엇인지 고려하며 일해야 한다!<br></li>
</ul>
<ol>
<li>주 고객이 사람이라면 -&gt; 슬라이드나 문서 형태로 결과를 전달한다.<ul>
<li>주식급등 요인 알아내기</li>
<li>고객 유형 분류 및 특징 파악</li>
<li>웹사이트 트래픽 분석 및 예측<br></li>
</ul>
</li>
<li>주 고객이 컴퓨터라면 -&gt; 데이터 분석 코드를 구현해 배포한다.<ul>
<li>고객에게 어떤 광고 보여줄지 결정하기</li>
<li>자동으로 데이터 분석하고 결과 보고서 작성하기</li>
</ul>
</li>
</ol>
</li>
</ol>
<h2 id="문제-파악">문제 파악</h2>
<blockquote>
<p>사업 면에서 어떤 문제가 있는지 파악하고, 어떻게 공학적으로 풀 수 있는지에 대해 정의한다.</p>
</blockquote>
<ul>
<li>상황에 맞는 정확한 질문을 찾아내는 능력을 갖추어야 한다</li>
<li>어떤 기능을 하는 프로그램을 만들지가 중요</li>
</ul>
<ol>
<li><p><strong>고객이 사람이라면</strong></p>
<ul>
<li>서비스의 문제점을 정확히 파악하고 있지만 해결방법을 찾지 못해서 데이터 분석하는 경우</li>
<li>서비스의 문제점을 파악하는 것이 목적인 경우</li>
</ul>
</li>
<li><p><strong>고객이 컴퓨터라면</strong></p>
<ul>
<li>이 프로젝트의 끝을 어떻게 정의할 것인가?</li>
<li>성능은 어느정도의 수준이 나와야 하는가?</li>
<li>어떤 조건을 만족해야 성공이라고 하는가?</li>
</ul>
</li>
</ol>
<blockquote>
<p>규모가 큰 프로젝트라면 요구사항과 목표를 문서화해야 한다!</p>
</blockquote>
<ol>
<li>외부에서 회사에 자문을 하는 경우 -&gt; <strong>작업기술서</strong></li>
<li>회사 내부에서 일하는 경우 -&gt; <strong>프로젝트 요구사항 문서</strong></li>
</ol>
<blockquote>
<p><strong>요구사항 문서에 들어가야 할 내용</strong>
<em>해결해야 할 문제들이 모호한 경우가 있다</em></p>
</blockquote>
<ul>
<li>어떤 문제가 있고</li>
<li>여러 문제 중 어떤것이 가장 중요하며</li>
<li>실제로 어느정도 해결이 가능한지</li>
</ul>
<p>차후에 문서화한 프로젝트 요구사항을 수정하기도 한다.</p>
<h2 id="데이터-분석-및-이해">데이터 분석 및 이해</h2>
<blockquote>
<p>실제로 데이터를 들여다 보며 문제 해결에 필요한 정보가 있는지, 어떻게 활용할지 알아낸다.</p>
</blockquote>
<blockquote>
<p><strong>데이터 종류와 관계 없이 확인해야 하는 보편적 질문</strong></p>
</blockquote>
<ol>
<li>데이터 셋의 크기는?</li>
<li>주어진 데이터가 일부인지, 전체인지</li>
<li>이 데이터가 모집단을 잘 대표하는지?</li>
<li>이상치나 잡음이 심하지 않은가?</li>
<li>원본 데이터가 아닌 임의 가공 데이터가 포함되어 있는가?</li>
<li>데이터별 식별자가 존재하는가?</li>
<li>식별자가 잘 설정되어 있는가? (중복이 있는가?)</li>
<li>두 데이터를 합쳐야 하는 경우 같은 종류의 데이터 셋인가?</li>
<li>누락된 데이터 표본이 있다면 왜 누락되었는가?</li>
</ol>
<p>여기서 가장 중요한 문제는 &quot;이 데이터로 주어진 문제를 풀 수 있는가?&quot;
처음부터 주어진 적절한 데이터가 있는지를 찾아봐야 한다.</p>
<h3 id="전처리"><em>전처리</em></h3>
<blockquote>
<p>원본 데이터를 분석에 사용하기 좋은 형태로 바꾸자!</p>
</blockquote>
<ol>
<li>전처리 프로그램 구현</li>
<li>전처리 프로그램으로 데이터 불러오기</li>
<li>불필요한 데이터 걸러내기</li>
<li>원하는 형태로 변환하여 분석에 적합한 형식으로 저장하기</li>
</ol>
<p>-&gt; 데이터 전처리는 통계학자와 구별되는 데이터 사이언티스트의 고유 업무!</p>
<p>전용 데이터베이스를 사용해 필요한 값을 저장한다.
데이터의 규모가 크고 복잡할수록 전처리 과정도 복잡해진다.
-&gt; 따라서 깔끔하고 효율적인 프로그램을 구현하는 능력이 중요하다!</p>
<blockquote>
<ol>
<li>문자열 데이터는 편집기를 써서 직접 살펴본다</li>
<li>특정 도구를 사용하는 경우 잘 작동하는지 확인한다 (csv파일이 잘 열리는지, 누락은 없는지)</li>
<li>히스토그램이나 산포도를 그려서 정말 말이 되는 분포인지 확인한다</li>
<li>이미 정답을 알고있는 문제를 푸는 코드를 짜서 그 결과가 정답과 일치하는지 확인한다.</li>
</ol>
</blockquote>
<h3 id="eda"><em>EDA</em></h3>
<blockquote>
<p>시각화, 다양한 변환을 통해 데이터를 확인한다.</p>
</blockquote>
<ul>
<li>데이터의 직관 키우기</li>
<li>시각화를 통해 데이터가 어떻게 이루어져 있는지, 어떤 성질이 있는지 가설 세우기</li>
</ul>
<br>


<h2 id="특징값-추출">특징값 추출</h2>
<blockquote>
<p>특징값을 추출하는 과정은 날것 그대로의 데이터를 가공해 그 값을 표에 저장하는 일</p>
</blockquote>
<p>각 행이 각 데이터 표본 하나, 열마다 다른 종류의 데이터 저장
예를 들어 이미지, 웹페이지, 음성은 각기 다른 특성을 가지고 있어 특징값의 의미와 추출 방법이 다르다. 
또는 스스로 특징값을 만들어야 하는 경우도 있다. </p>
<br>

<h2 id="모델-수집-및-분석">모델 수집 및 분석</h2>
<blockquote>
<p>머신러닝 모델을 사용해 분석하자!</p>
</blockquote>
<ol>
<li>고객의 충성도를 0~1 값으로 나타내고자 한다면 -&gt; 회귀 모델 사용</li>
<li>다양한 고객을 몇가지 범주로 분류한다면 -&gt; 군집화 모델 사용</li>
</ol>
<br>


<h2 id="결과-정리-및-발표">결과 정리 및 발표</h2>
<p>고객이 사람이라면 -&gt; 슬라이드, 보고서
고객이 컴퓨터라면 -&gt; 코드, 보고서</p>
<h3 id="코드배포">코드배포</h3>
<ol>
<li>배치 분석 코드<ul>
<li>가지고 있는 전체 데이터를 한번에 분석하는 코드</li>
</ul>
</li>
<li>실시간 분석 코드<ul>
<li>데이터를 실시간으로 추가해 분석하는 코드 </li>
<li>일반적으로 전체 시스템의 모듈로 작동</li>
</ul>
</li>
</ol>
<blockquote>
<p>코드 배포 시 필요한 결과물</p>
</blockquote>
<ol>
<li>결과 코드</li>
<li>코드 실행 시 필요한 도움말 문서 (readme/주석)</li>
<li>결과 코드 검증 위한 시험 코드</li>
</ol>
<br>

<h2 id="반복작업">반복작업</h2>
<blockquote>
</blockquote>
<ol>
<li>데이터에 대한 직관이 생길때까지 산포도, 히스토그램을 그려보고 간단한 특징값을 사용해 작동하는지 확인한다.<ul>
<li>현 데이터로는 애초에 풀 수 없는 문제일수도 있다</li>
</ul>
</li>
</ol>
<blockquote>
<ol start="2">
<li>모든 실험을 명령어 하나로 실행할 수 있도록 분석을 자동화하는 스크립트 만들기</li>
</ol>
</blockquote>
<blockquote>
<ol start="3">
<li>단계별로 코드를 나누고 내부 단계에서도 여러 기능을 모듈화하라</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Streamlit] 기본 문법]]></title>
            <link>https://velog.io/@do_genie/Streamlit-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@do_genie/Streamlit-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sat, 09 Dec 2023 09:06:30 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행할 때, 만든 모델을 다른 사람에게 공유하고, 보여주고 싶은 경우 사용할 수 있는 대시보드 </p>
<p>간단하게 실행 가능한 도구 = streamlit 
python으로 web 구현하기 </p>
<h2 id="streamlit">Streamlit</h2>
<h3 id="제목-설정하기">제목 설정하기</h3>
<h4 id="타이틀">타이틀</h4>
<pre><code class="language-python">st.title(&quot;Title&quot;)</code></pre>
<h4 id="헤더">헤더</h4>
<pre><code class="language-python">st.header(&quot;Header&quot;)</code></pre>
<h4 id="서브헤더">서브헤더</h4>
<pre><code class="language-python">st.subheader(&quot;subheader&quot;)</code></pre>
<h4 id="텍스트-작성">텍스트 작성</h4>
<pre><code class="language-python">st.title(&quot;Text&quot;)</code></pre>
<h3 id="캐싱">캐싱</h3>
<ul>
<li>특정 버튼 누를 때 데이터 불러오기 -&gt; 데이터 반복으로 불러오기 X -&gt; 중간에 캐싱하면 속도 개선 가능 </li>
<li>데코레이터 사용해 캐싱 진행 <ul>
<li>데코레이터란? 
  함수를 장식하는 도구
  <em>def 함수(함수)</em></li>
<li>함수 이름 확인</li>
<li>함수 구성하는 코드 확인</li>
<li>함수 호출 시 사용한 매개변수
=&gt; 위 세개 확인해 로컬에 저장, 다시 호출시 캐싱 사용 가능하면 사용<pre><code>@st.cache
def load_data():
return data</code></pre></li>
</ul>
</li>
</ul>
<h3 id="위젯">위젯</h3>
<ul>
<li><p>버튼 만들기</p>
<pre><code class="language-python">if st.button(&quot;click button&quot;):
    st.write(&quot;Data Loading..&quot;)
    load_data()</code></pre>
</li>
<li><p>체크박스 </p>
<pre><code class="language-python">checkbox_btn = st.checkbox(&#39;Checktbox Button&#39;, value = True) #디폴트 체크

if checkbox_btn:
    st.write(&#39;Great!&#39;)</code></pre>
</li>
<li><p>라디오 버튼</p>
<pre><code class="language-python">selected_item = st.radio(&quot;Radio Part&quot;, (&quot;A&quot;, &quot;B&quot;, &quot;C&quot;))

if selected_item == &quot;A&quot;:
    st.write(&quot;A!!&quot;)
elif selected_item == &quot;B&quot;:
    st.write(&quot;B!&quot;)
elif selected_item == &quot;C&quot;:
    st.write(&quot;C!&quot;)</code></pre>
<p>첫 요소가 디폴트로 선택된다. </p>
</li>
<li><p>선택박스 </p>
<pre><code class="language-python">option = st.selectbox(&#39;Please select in selectbox!&#39;,
                     (&#39;kyle&#39;, &#39;seongyun&#39;, &#39;zzsza&#39;))

st.write(&#39;You selected:&#39;, option)</code></pre>
</li>
<li><p>다중 선택박스 </p>
<pre><code class="language-python">multi_select = st.multiselect(&#39;Please select somethings in multi selectbox!&#39;,
                              [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;])

st.write(&#39;You selected:&#39;, multi_select)</code></pre>
<p>결과가 배열로 나온다. </p>
</li>
<li><p>슬라이더</p>
<pre><code class="language-python">values = st.slider(&#39;Select a range of values&#39;, 0.0, 100.0, (25.0, 75.0))
st.write(&#39;Values:&#39;, values)</code></pre>
</li>
</ul>
<h3 id="데이터-입력">데이터 입력</h3>
<pre><code class="language-python">#텍스트 데이터
  st.text_input(value)
#텍스트 데이터를 암호로 사용 
  st.text_input(label, value, type=&quot;password&quot;)
# 숫자 데이터 
  st.number_input(label, value)
# 여러줄의 텍스트 데이터
  st.text_area(label, value)
#날짜 입력
  st.date_input(label, value)
#시간 입력
  st.time_input(label, value) </code></pre>
<h3 id="데이터-출력">데이터 출력</h3>
<pre><code class="language-python">  st.write(&quot;st.dataframe api&quot;) #st.dataframe 사용하면 인터렉티브 테이블
  df = pd.DataFrame(np.random.randn(5, 2), columns=(&#39;col %d&#39; % i for i in range(2)))
  st.dataframe(df.style.highlight_max(axis=0)) #최대값에 하이라이트 

  st.write(&quot;st.table api&quot;) #st.table 사용하면 static한 테이블
  st.table(df)</code></pre>
<h3 id="차트-출력">차트 출력</h3>
<pre><code class="language-python">st.line_chart(df)
st.area_chart(df)
st.bar_chart(df)
st.pyplot(df)
st.altair_chart(df)
st.vega_lite_chart(df)
st.plotly_chart(df)
st.bokeh_chart(df)
st.pydeck_chart(df)
st.graphviz_chart(df)
st.map(df)</code></pre>
<h3 id="progress-status">progress, status</h3>
<pre><code class="language-python">st.success(&quot;성공메세지&quot;)
st.error(&quot;error&quot;)
st.warning(&quot;Warning&quot;)
st.info(&quot;info&quot;)

import time
# 코드 실행 도중에 출력하는 메세지
with st.spinner(&quot;코드 실행중&quot;):
    time.sleep(5) 
st.success(&quot;완료&quot;)</code></pre>
<h3 id="이미지-비디오-오디오">이미지, 비디오, 오디오</h3>
<pre><code class="language-python">from PIL import Image
image = Image.open(&quot;img.jpg&quot;)
st.image(image)


video = open(&quot;videpo.mp4&quot;, &quot;rb&quot;)
video_bytes = video.read()
st.video(video_bytes)


audio = open(&quot;audio.ogg&quot;, &#39;rb&#39;)
audio_bytes = audio.read()
st.audio(audio_bytes, format = &#39;audio/ogg&#39;)</code></pre>
<h3 id="사이드바-레이아웃">사이드바, 레이아웃</h3>
<pre><code class="language-python">#웹페이지 왼쪽에 사이드바 추가
add_selectbox = st.sidebar.selectbox(&quot;왼쪽 사이드바 Select Box&quot;, (&quot;A&quot;, &quot;B&quot;, &quot;C&quot;))

#st.beta_columns 사용해 레이아웃 나누기
col1, col2, col3 = st.beta_columns(3)

#첫번째 열
with col1:
   st.header(&quot;A cat&quot;)
   st.image(&quot;https://static.streamlit.io/examples/cat.jpg&quot;, use_column_width=True)

#두번째 열 
with col2:
   st.header(&quot;Button&quot;)
   if st.button(&quot;Button!!&quot;):
       st.write(&quot;Yes&quot;)

#세번째 열
with col3:
    st.header(&quot;Chart Data&quot;)
    chart_data = pd.DataFrame(np.random.randn(50, 3), columns=[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;])
    st.bar_chart(chart_data)
</code></pre>
<p><a href="https://cheat-sheet.streamlit.app/">https://cheat-sheet.streamlit.app/</a></p>
<h3 id="streamlit-배포">streamlit 배포</h3>
<ol>
<li>Heroku
 <a href="https://www.heroku.com/">https://www.heroku.com/</a></li>
<li>streamlit 자체 제공 기능 </li>
<li>깃헙</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[LLM이란?]]></title>
            <link>https://velog.io/@do_genie/LLM%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@do_genie/LLM%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sat, 02 Dec 2023 12:03:14 GMT</pubDate>
            <description><![CDATA[<p>LM (언어 모델, Language Model) 이란, 인간의 언어를 이해하고 생성하도록 훈련된 일종의 인공지능 모델이다. 언어 모델의 품질은 크기나 훈련된 데이터의 양 및 다양성, 훈련 중에 사용된 학습 알고리즘의 복잡성에 따라 달라진다.</p>
<p>LLM (거대 언어 모델, Large Language Model) 이란, 대용량의 언어 모델을 의미한다. LLM은 딥 러닝 알고리즘과 통계 모델링을 통해 자연어 처리(Natural Language Processing, NLP) 작업을 수행하는 데에 사용한다. 이 모델은 사전에 대규모의 언어 데이터를 학습하여 문장 구조나 문법, 의미 등을 이해하고 생성할 수 있다.</p>
<p>예를 들어, 주어진 문맥에서 다음 단어를 예측하는 문제에서 LLM은 문장 내의 단어들 사이의 유사성과 문맥을 파악하여 다음 단어를 생성할 수 있다. 이러한 작업은 기계 번역, 텍스트 요약, 자동 작문, 질문 응답 등 다양한 NLP 과제에 활용된다. LLM은 GPT(Generative Pre-trained Transformer)와 BERT(Bidirectional Encoder Representations from Transformers)와 같은 다양한 모델들이 있다. 이러한 모델들은 수천억 개의 매개변수를 가지고 있다. 최근에는 대용량의 훈련 데이터와 큰 모델 아키텍처를 사용하여 더욱 정교한 언어 이해와 생성을 달성하는데 주목을 받고 있다.
<br/>
<br/></p>
<h2 id="nlp-vs-llm">NLP vs. LLM</h2>
<p>NLP와 LLM은 관련이 있는 개념이지만, 서로 다른 개념이다. </p>
<p>NLP는 인간의 언어를 이해하고 처리하는 데 초점을 맞춘 인공지능 분야이다. NLP는 컴퓨터가 자연어 텍스트를 이해하고 분석하는 기술을 개발하는 것을 목표로 한다. NLP는 문장 구문 분석, 텍스트 분류, 기계 번역, 질의 응답 시스템, 감정 분석 등과 같은 다양한 작업에 활용된다.</p>
<p>반면 LLM은 큰 데이터셋을 사용하여 훈련된 대용량의 언어 모델을 가리킵니다. 딥 러닝 기술과 통계 모델링을 사용하여 자연어 처리 작업을 수행할 수 있다. </p>
<p>즉, <strong>NLP는 자연어 처리 분야 전반을 아우르는 개념</strong>이며, <strong>텍스트를 이해하고 처리</strong>하는 기술에 초점을 둡니다. LLM은 <strong>NLP의 한 부분</strong>으로, 대량의 언어 데이터를 바탕으로 학습된 언어 모델을 사용하여 <strong>특정 NLP 작업을 수행</strong>하는데 초점을 둡니다. NLP는 더 넓은 의미의 개념이며, LLM은 그 안에서 특정한 접근 방식과 모델을 가리키는 한 가지 형태입니다.
<br/></p>
<h2 id="llm-거대-언어-모델-작동-원리">LLM (거대 언어 모델) 작동 원리</h2>
<p><strong>언어 모델의 유형</strong>
모델 개발 단계는 다음과 같다.</p>
<ul>
<li>*<em>SLM (Small Language Model): *</em>제한된 양의 텍스트 데이터를 학습하여, 작업 전반에 걸쳐 국소적인 문맥을 이해하는 데에 초점을 맞춥니다. 작은 규모에도 불구하고, SLM은 가볍고 실행 속도도 빠른 특징을 가지고 있습니다.</li>
<li><strong>NLM (Neural Language Model):</strong> NLM은 기존의 통계 기반 언어 모델보다 더 정확한 성능을 제공합니다. 이러한 모델은 주로 단어 임베딩, 문장 완성, 기계 번역 등 다양한 NLP 작업에 사용됩니다.</li>
<li><strong>PLM (Pretrained Language Model):</strong> PLM은 대규모 데이터셋으로 미리 학습되며, 이후 다양한 NLP 작업에 전이학습(Transfer Learning)을 통해 적용됩니다. BERT와 GPT와 같은 주요 모델들은 이 PLM에 속합니다.</li>
</ul>
<p>연구자들은 PLM을 확장하면 다운스트림 작업에서 모델 용량이 향상될 수 있다는 사실을 발견했다. 많은 연구에서 훨씬 더 큰 PLM을 훈련하면서 성능 한계를 탐색해보고자 했다. 이러한 대형 PLM은 소형 PLM과는 다르게, 일련의 복잡한 작업을 해결할 때 놀라운 능력을 발휘한다는 점이 밝혀졌다. 예를 들어, GPT-3는 상황을 학습하여 단발성 과제를 해결할 수 있는 능력을 가졌지만 GPT-2는 그렇지 못했다. 따라서 연구 커뮤니티에서는 <strong>이러한 대형 PLM을 두고 “대규모 언어 모델(LLM)”이라는 용어를 사용하기 시작</strong>했습니다. 즉, LLM은 언어 모델의 현주소이자 최종 개발 단계라고 할 수 있습니다.</p>
<br/>
<br/>


<h2 id="llm-용어">LLM 용어</h2>
<ul>
<li>단어 임베딩: 단어들을 고차원 벡터로 표현하여 각 단어 간의 유사성과 관계를 캡처하는 기술</li>
<li>주의 메커니즘: 입력 시퀀스의 다양한 부분에 가중치를 부여하여 모델이 중요한 정보에게 집중할 수 있도록 하는 기술</li>
<li>Transformer: 주의 메커니즘을 기반으로 한 인코더와 디코더 구조의 신경망 모델로, 길이가 다른 시퀀스를 처리하는 데 탁월한 성능</li>
<li>Fine-tuning LLMs: 사전 학습된 대규모 언어 모델을 특정 작업에 적용하기 위해 추가 학습하는 과정</li>
<li>Prompt engineering: 모델에 입력하는 질문이나 명령을 구조화하여 모델의 성능을 향상시키는 과정</li>
<li>Bias (편향): 모델이 학습 데이터의 불균형이나 잘못된 패턴을 포착하여 실제 세계의 현실과 일치하지 않는 결과를 내놓는 경향</li>
<li>해석 가능성: LLM이 가진 복잡성을 극복하고 AI 시스템의 결과와 결정을 이해하고 설명할 수 있는 능력</li>
</ul>
<p><img src="https://velog.velcdn.com/images/do_genie/post/469d5d09-acdc-4650-ad13-71378210b83c/image.png" alt="">
 LLM이 언어를 학습하는 과정에는 딥 러닝의 원리가 활용된다. LLM은 딥 러닝의 방식으로 방대한 양을 사전 학습(Pre-trained)한 전이 학습 (Transfer) 모델이라고 할 수 있다.
 LLM은 문장에서 가장 자연스러운 단어 시퀀스를 찾아내는 딥 러닝 모델이다. 
 문장 속에서 이전 단어들이 주어지면 다음 단어를 예측하거나 주어진 단어들 사이에서 가운데 단어를 예측하는 방식으로 작동한다. </p>
<p>  LLM을 학습시키는 방법은 대부분 큰 양의 텍스트 데이터를 기계학습 알고리즘에 입력하는 것이다. 이때 일반적으로, 먼저 토큰화(tokenization)과 같은 전처리 과정을 거쳐 문자열 데이터를 분리한 다음, BERT, GPT, GPT-2, GPT-3, T5 등의 모델을 사용하여 학습한다.</p>
<h2 id="파인튜닝프롬프트-튜닝">파인튜닝/프롬프트 튜닝</h2>
<p><strong>파인 튜닝 (Fine-tuning)</strong></p>
<p>사전 학습된 언어 모델 전체를 대상으로 추가 작업 데이터를 이용하여 모델을 재학습시키는 방법법. 사전 학습한 모델을 초기 가중치로 사용하고, 특정 작업에 대한 추가 학습 데이터로 모델을 재학습</p>
<ul>
<li>모델 파라미터의 일부 또는 전체를 재학습하기 때문에 작업 특정성(task-specific)이 높은 모델을 얻을 수 있다. </li>
<li>대량의 추가 작업 데이터가 필요할 수 있다. </li>
<li>일반적으로 새로운 작업에 대해 파인 튜닝하는 데 시간이 오래 걸릴 수 있다.</li>
<li>특정 작업에 특화된 예측 수행 가능성이 높아진다.</li>
</ul>
<p><strong>프롬프트 튜닝 (Prompt tuning)</strong></p>
<p>입력 텍스트에 특정 구조화된 프롬프트(prompt)를 추가하거나 수정하여 모델의 동작을 조정하는 방법. 특정 작업에 맞는 최적의 프롬프트 구성을 실험하고, 모델 출력을 조작하여 원하는 결과를 얻을 수 있도록 모델을 조정.</p>
<ul>
<li>사전 학습된 모델의 파라미터를 고정하고, 프롬프트 구성을 조정하여 특정 작업에 적합한 결과를 얻는다.</li>
<li>기존 데이터에 추가 작업하지 않아도 되므로 데이터 확보에 대한 부담을 줄일 수 있다.</li>
<li>작업 특정성이 낮고, 다양한 작업에 대해 유연한 조정이 가능.</li>
<li>초기 설정과 프롬프트 구성에 대한 실험이 필요하며, 설정에 따른 성능 차이가 있을 수 있다.</li>
</ul>
<p>출처 : <a href="https://www.thedatahunt.com/trend-insight/what-is-llm">https://www.thedatahunt.com/trend-insight/what-is-llm</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Artificial Neural Networks with Keras]]></title>
            <link>https://velog.io/@do_genie/Artificial-Neural-Networks-with-Keras</link>
            <guid>https://velog.io/@do_genie/Artificial-Neural-Networks-with-Keras</guid>
            <pubDate>Sat, 02 Dec 2023 11:44:58 GMT</pubDate>
            <description><![CDATA[<h2 id="neurons의-논리연산">Neurons의 논리연산</h2>
<p>적어도 입력이 둘은 있어야 출력 1개가 나온다. (뉴런이 활성화 된다)</p>
<h2 id="퍼셉트론이란">퍼셉트론이란?</h2>
<p>TLU(Threshold Logi unit), LTU(linear threshold unit)</p>
<p><strong>TLU</strong></p>
<ul>
<li>가중합을 계산한다 (input은 이진이 아니라 숫자)</li>
<li>step function으로 분류한다.</li>
</ul>
<h3 id="step-function의-종류">step function의 종류</h3>
<ol>
<li>heaviside ⇒ 0/1로 나누어짐</li>
<li>sgn ⇒ -1, 0, 1로 나누어짐</li>
</ol>
<h3 id="single-tlu">single TLU</h3>
<ul>
<li>심플 선형 분류</li>
<li>입력선형조합을 계산함</li>
<li>임계값 넘으면 양성, 안넘으면 음성</li>
<li>여기서 영향을 주는 가중치 (W)를 찾는 것이 주 목표이다</li>
</ul>
<h3 id="2개의-인풋과-3개의-아웃풋을-가지는-퍼셉트론">2개의 인풋과 3개의 아웃풋을 가지는 퍼셉트론</h3>
<p>각각의 TLU는 모든 Input과 연결되어 있다. (한개의 층)</p>
<p>완전연결층의 출력을 계산하는 방법은 각각의 가중합을 계산한 뒤 활성함수에 넣는 것을 말한다. </p>
<p>바이어스는 모든 연결된 가중치에 포함된다. </p>
<h3 id="가중치-업데이트">가중치 업데이트</h3>
<p>그 전의 가중치 + 학습률<em>(오차)</em>입력</p>
<h2 id="퍼셉트론-수렴이론">퍼셉트론 수렴이론</h2>
<p>각 출력 뉴런의 decision boundary를 선형으로 갖는 단층 퍼셉트론은 복잡한 문제를 학습할 수 없다 .</p>
<p>하지만 만약 트레이닝 샘플이 선형구분 된다면 해당 알고리즘은 정답에 수렴한다. </p>
<h2 id="퍼셉트론의-한계">퍼셉트론의 한계</h2>
<ol>
<li><p>싱글 퍼셉트론은 클래스의 <strong>확률을 출력하지 않는다.</strong> </p>
<p> 이는 로지스틱 회귀를 퍼셉트론보다 더 선호하는 이유이다. </p>
</li>
<li><p><strong>XOR과 같은 문제는 풀지 못한다.</strong> </p>
</li>
</ol>
<p>⇒ 따라서 MLP를 사용한다( 다층퍼셉트론)</p>
<h2 id="다층-퍼셉트론과-역전파">다층 퍼셉트론과 역전파</h2>
<p>입력층→은닉층→출력층으로 구성되어 있다. </p>
<p>입력층 → lower layer</p>
<p>출력층 → upper layer</p>
<p>은닉층 ⇒ bias 포함</p>
<p><strong>MLP의 단점:</strong> 직관적으로 알기 어렵다 (Black BOX)</p>
<h2 id="dnn">DNN</h2>
<p>deep stack of computation을 말한다 </p>
<p>deep stack of hidden layer</p>
<p><strong>역전파 실행과정</strong></p>
<ul>
<li>자동으로 Gradient Descent를 찾는다.</li>
<li>네트워크 에러의 gradient를 찾는다.</li>
<li>error를 줄일 수 있는 가중치와 바이어스를 찾는다.</li>
<li>정답에 수렴할 때 까지 역전파를 실행한다.</li>
</ul>
<p><strong>그 전의 가중치 + 학습률<em>(오차)</em>입력</strong></p>
<ul>
<li>임의로 초반 가중치를 초기화 해야함</li>
<li>가중치와 바이어스가 모두 0이면 모든 뉴런이 동일하다</li>
<li>랜덤으로 가중치를 설정했다면 역전파가 필요하다</li>
</ul>
<hr>
<p><strong>Forword Pass (순전파)</strong></p>
<ul>
<li>하나의 미니배치를 갖고 각각의 통과를 에포크라고 한다.</li>
<li>인풋레이어를 지나친 미니배치는 첫번째 히든레이어를 지난다.</li>
<li>히든 레이어를 지나온 뉴런의 모든 아웃풋을 계산한다.</li>
<li>아웃풋 레이어에 도달할 때 까지 이를 반복한다.</li>
</ul>
<p><strong>Backward Pass (역전파)</strong></p>
<ul>
<li>아웃풋과 기대값의 차이를 구한다(에러)</li>
<li>chain rule을 적용한다.</li>
<li>뒤로 돌아가면서 다음 가중치를 업데이트 한다.</li>
</ul>
<h2 id="활성함수역전파">활성함수(역전파)</h2>
<ol>
<li>스텝함수
미분 불가능</li>
<li>sigmoid 함수
미분 가능, 0과 1사이로 나옴</li>
<li>tanh함수
연속, 미분가능, -1~1사이 값으로 나옴</li>
<li>ReLU함수
0에서는 구분하지 않고, 그 이후부터 구분함, 계산속도 올라감, 최대 출력값이 없음(한계X)</li>
</ol>
<h2 id="mlp-회귀">MLP 회귀</h2>
<ol>
<li>한개 값 예측하기 → single 출력 뉴런</li>
<li>다중회귀→ multiple 출력 뉴런</li>
</ol>
<p>활성함수 (은닉층)</p>
<ol>
<li>모든 범위 값 출력 → 활성함수 없음</li>
<li>항상 양수 출력 → relu</li>
<li>값이 양수면 양수, 아니면 0 →softPlus (relu업그레이드)</li>
<li>0~1 → logistic(시그모이드)</li>
<li>-1~1 → tanh</li>
</ol>
<p><strong>loss function</strong></p>
<ol>
<li>MSE (quadratic)</li>
<li>MAE (linear)</li>
<li>Huber loss (quadratic + linear)</li>
</ol>
<p><strong>Huber loss란?</strong></p>
<p>2차와 1차 사이에 존재하는 loss fonction</p>
<p>2차의 장점: 빠르고 정밀</p>
<p>1차의 장점: 이상치에 덜 민감</p>
<p>임계값보다 에러가 작으면 quadratic, 임계값보다 에러가 크면 linear를 섞어 쓰는 Loss function</p>
<h2 id="mlp-분류">MLP 분류</h2>
<ol>
<li>이진분류<ol>
<li>logistic 활성함수 사용</li>
<li>log loss 사용 (Cross entropy)</li>
<li>양성확률이 0~1 사이의 값으로 나옴, 1에서 빼면 음성</li>
</ol>
</li>
<li>multilabel binary 분류 (1,A)<ol>
<li>logistic 활성함수 사용</li>
<li>log loss 사용 (Cross entropy)</li>
<li>아웃풋 뉴런이 1개의 레이블 마다 1개씩 있음</li>
</ol>
</li>
<li>multiclass 분류 (1 or 2 or 3)<ol>
<li>softmax 활성함수 사용 (은닉층은 ReLU)</li>
<li>log loss 사용</li>
<li>각 클래스마다 확률 나옴(합은 1)</li>
<li>아웃풋 뉴런이 1개의 클래스마다 1개씩 있음</li>
</ol>
</li>
</ol>
<h2 id="시퀀셜-라이브러리-api">시퀀셜 라이브러리 (API)</h2>
<p>: 케라스 신경망 모델</p>
<ul>
<li>순서대로 1층씩 쌓아서 시퀀셜이라고 함</li>
</ul>
<h2 id="층-만들고-학습시키기">층 만들고 학습시키기</h2>
<p><strong>add로 추가할 것</strong></p>
<p>flatten(입력 이미지 1차원 배열)</p>
<p>dense(은닉층 추가) , 앞에 뉴런개수 설정 가능, activation 함수 설정 가능</p>
<ul>
<li>dense의 마지막은 softmax로 설정해 분류가 가능하게 한다.</li>
</ul>
<p><strong>summary() → 각 층의 정보 확인 가능</strong></p>
<p>각 층의 파라미터는 <strong>이전 층의 뉴런 개수*지금 뉴런의 개수</strong> </p>
<p>파라미터 접근을 위한 메서드</p>
<ul>
<li>set_weights()</li>
<li>get_weights()</li>
</ul>
<p>가중치를 랜덤으로 초기화할 수 있다. 원한다면 kernel_initializer, bias_initializer()로 설정 가능</p>
<p><strong>complie → 손실함수와 옵티마이저 지정</strong></p>
<p>loss 방법, 옵티마이저 방법, 점수 기준 설정</p>
<p><strong>loss 설정</strong></p>
<p>if) 다중클래스라면 </p>
<p>if) 샘플마다 클래스별 타깃 확률을 가진다면 [[0.5, 0.5], [1, 0]]→ categorial_crossentropy</p>
<p>if) 샘플마다 레이블이 정수로 되어있다면[1, 2] → Sparse_categorial_crossentropy</p>
<p>if) 이진, 다중레이블이라면 → sofrmax 대신 sigmoid / binary_crossentropy </p>
<p>sparse label을 one-hot-vector를 사용해 categorial로 바꿀 수 있다. </p>
<p><strong>옵티마이저 설정</strong></p>
<p>SGD, ADAM 등</p>
<p>lr (학습률)설정 가능 → 기본값 0.01</p>
<p><strong>fit → 모델 학습</strong></p>
<ul>
<li>validation set 설정 가능</li>
<li>training set 이 validtion보다 너무 좋다면 overfitting</li>
</ul>
<p>history</p>
<p>파라미터, 에포크, val set에 대한 손실 측정한 지표</p>
<p><strong>그래프를 그렸을 떄 검증손실은 에포크가 실행되고 나서 계산되고, 훈련손실은 에포크 진행동안 계산되기 때문에 훈련 손실이 에포크의 절반만큼 왼쪽으로 이동해야 한다.</strong> </p>
<h2 id="치우친-데이터의-경우">치우친 데이터의 경우</h2>
<p>Skewed data</p>
<p><strong>class_weight</strong> → 과소표현된 클래스에 더 큰 가중치, 과대표현된 클래스에 더 작은 가중치 주기</p>
<p><strong>per-instance weight</strong> → 일회용 가중치</p>
<h2 id="파라미터-튜닝">파라미터 튜닝</h2>
<p>층 수 , 층 속 뉴런 수, 활성함수 타입, 배치사이즈 등을 바꿔본다. </p>
<p>검증 정확도가 만족스러우면 테스트셋으로 일반화 오류를 측정한다. (검증보다 테스트가 성능 낮은게 일반적)</p>
<p><strong>evaluate 사용</strong></p>
<h2 id="모델-사용해-예측하기">모델 사용해 예측하기</h2>
<p><strong>predict 사용</strong></p>
<p>샘플별 각 클래스별로 확률 도출된다. </p>
<p>predict_class 사용하면 샘플의 클래스가 뜬다. </p>
<h2 id="회귀용-mlp-만들기">회귀용 MLP 만들기</h2>
<p><strong>분류와 다른 점</strong></p>
<ol>
<li>출력층이 하나의 뉴런이다.</li>
<li>활성화 함수가 출력층에 없다</li>
<li>MSE사용된다. (loss function)</li>
</ol>
<p><strong>분류와 같은 점</strong></p>
<ol>
<li>시퀀셜 API 사용한다.</li>
</ol>
<h2 id="더-복잡한-모델을-만들-때-functional-api">더 복잡한 모델을 만들 때 Functional API</h2>
<p>wide and deep 모델</p>
<p>: 입력의 일부, 전체가 출력층과 바로 연결된다. </p>
<ul>
<li>일반적 MLP는 네트워크에 있는 층 전체에 모든 데이터를 통과시킨다.  → 연속변환은 데이터 흐트러질 수 있음</li>
<li>층이 만들어지자마자 함수처럼 호출된다. (파라미터로 입력층과 은닉층1을 호출한다)</li>
<li>concat을 사용해 input 과 은닉층을 연결시킨다.</li>
<li>회귀이므로 출력층에 활성함수 없음</li>
</ul>
<p>모델은 인풋과 아웃풋만을 정의하고 끝난다. </p>
<p>wide conponent → 일반화된 선형모델을 말한다. </p>
<p>deep component→ feed-forward 모델을 말한다. </p>
<p>일부 특성을 짧은 경로로 전달, 다른 경로를 깊은 경로로 전달할 때 사용된다. </p>
<p>이때, 따로따로 계산한다 (A, B라고 두고 train, test, val 모두 따로따로 계산)</p>
<ul>
<li>fit , eval, predict 모두 괄호로 묶어 계산</li>
</ul>
<h2 id="multiple-output을-가질-때">multiple output을 가질 때</h2>
<ol>
<li>여러 출력이 필요할 때 (너비, 높이)</li>
<li>동일한 데이터에서 독립적인 여러 작업이 필요할 때 (1. 표정, 2. 안경유무)</li>
<li><strong>규제기법을 사용하는 경우</strong></li>
</ol>
<h3 id="규제기법">규제기법</h3>
<p>: 보조출력을 추가하는 경우 → 과적합을 줄여 일반화 능력을 향상시킨다. </p>
<ul>
<li>적절한 층에 연결시키고 출력리스트에 추가한다.</li>
<li>네트워크의 기본 부분이 나머지 부분에 의존하지 않고 자체적으로 유용한 것을 학습하도록 한다.</li>
</ul>
<ol>
<li>extra output을 추가한다. </li>
<li>각각의 로스함수를 갖는다 
모델 컴파일 시 손실 리스트를 전달해야 한다
보조 출력보다 주 출력에 관심이 많다면 주출력에 가중치 키운다. (주로 보조 출력을 규제로 사용)</li>
<li>각 레이블을 부여한다. (주, 보조출력의 예측이 같다면 두개 다 같게 둔다)</li>
</ol>
<h2 id="subclassing-api-사용하는-경우">Subclassing API 사용하는 경우</h2>
<p>:동적 모델 만들 때 </p>
<p><strong>시퀀셜과 함수형은 선언적이다.</strong></p>
<p>사용 층, 연결 방식 정의 후에 데이터를 주입해 학습한다. </p>
<p><strong>장점</strong></p>
<ol>
<li>모델을 저장, 복사, 공유하기 쉽다.</li>
<li>모델의 구조를 파악하기 쉽다.</li>
<li>프레임워크의 크기를 짐작하고 타입을 확인해 에러를 줄일 수 있다</li>
<li>디버깅하기 쉽다. </li>
</ol>
<p><strong>단점</strong></p>
<ol>
<li>정적인게 단점</li>
</ol>
<p><strong>장점</strong></p>
<p><strong>서브클래싱 API는 반복, 다양한 형태 등 구현이 가능</strong></p>
<ul>
<li>모델 클래스 만들고 생성자 안에서 필요 층 만들기</li>
<li>call 메서드 안에서 수행연산 기술</li>
<li>input 객체가 필요없다. (call의 input()사용하면 됨)</li>
</ul>
<p><strong>단점</strong></p>
<ol>
<li>공유, 저장, 복사 어려움</li>
<li>사전에 종류나 모양을 파악하기 어려움</li>
<li><strong>실수 만들기 쉬움</strong></li>
<li>summary시 층의 리스트밖에 못얻음(정보없음)</li>
<li>유연성 높아지면 비용 발생</li>
</ol>
<p>subclassing에서는 <a href="http://model.save">model.save</a> 사용 불가능하므로 save_weight(), load_weighr() 사용해야한다. </p>
<h2 id="callback-사용">CallBack 사용</h2>
<p>조기종료 사용</p>
<ol>
<li>훈련이 몇시간동안 진행되는 경우 체크포인트 필요</li>
<li>일정 에포크 동안 검증셋의 점수 향상이 안되면 stop (patience) → 에포크 커도 됨</li>
</ol>
<p>EarlyStopping → 종료에 관여, 직후 어떤 모델의 가중치를 return할지 설정 가능</p>
<p>ModelCheckPoint → 저장에 관여, 직후 어떤 모델의 가중치 리턴할지 관여 안함</p>
<p>두개 같이 사용 가능</p>
<h3 id="custom-callback">Custom callback</h3>
<p>검증 로스와 훈련 로스의 비율을 훈련동안 정하기 가능</p>
<h2 id="텐서보드로-시각화-하기">텐서보드로 시각화 하기</h2>
<ol>
<li>학습곡선 그리기</li>
<li>여러 실행간의 학습곡선 비교 </li>
<li>계산그래프 시각화</li>
<li>통계분석</li>
<li>모델생성 이미지</li>
<li>3D에 투영된 다차원 데이터 시각화</li>
</ol>
<p>텐서보드 서버</p>
<ol>
<li>로그 디렉토리 모니터링</li>
<li>자동으로 변경사항 읽기</li>
<li>실시간 데이터 시각화</li>
</ol>
<p>루트디렉토리 밑에 다른 디렉토리 설정해 기록해 여러번 실행 가능 → 훈련하는 동안 이벤트 파일 만들고 서머리 기록</p>
<p>실행마다 하나의 디렉토리 설정, train, validation으로 서브디렉토리 설정</p>
<p>train에는 성능 병목지점 찾는 profileing trace 존재</p>
<h3 id="summary-package">summary package</h3>
<ol>
<li>스칼라</li>
<li>히스토그램</li>
<li>이미지</li>
<li>텍스트</li>
<li>오디오 </li>
</ol>
<p>기록 가능</p>
<h2 id="하이퍼-파라미터-파인튜닝">하이퍼 파라미터 파인튜닝</h2>
<ol>
<li><p>많은 파라미터 조합 실행해보고 val set에서 가장 좋은 성능을 내는 파라미터로 설정하기</p>
<p> 하이퍼파라미터 공간 탐색 필요</p>
<ol>
<li><p>케라스 모델을 사이킷런 추정기처럼 보이게 바꾼다</p>
</li>
<li><p>케라스 모델 만들고 컴파일한다. </p>
</li>
<li><p>build model 사용해 케라스회귀 객체 만든다</p>
<p>사이킷런은 손실이 아니라 점수를 계산하기 때문에 음수의 MSE나온다. </p>
<p>이때 randomized search가 많이 사용된다→ 하이퍼파라미터 객체가 많기 때문이다. </p>
</li>
<li><p>검증셋에서 제일 좋은 결과 찾는댜 (val 따로 필요 없음 → k-fold 사용함)</p>
</li>
<li><p>test set으로 일반화 오류 찾기</p>
</li>
</ol>
</li>
</ol>
<p>훈련에 시간이 많이 걸리면 탐색할 파라미터 공간에 제약이 생긴다. → 수동으로 탐색과정을 보조할 수 있으나 시간 많이 든다. </p>
<p>탐색 지역이 더 좋다고 판명될 때 더 탐색을 수행하는 방법이 있음</p>
<h2 id="히든레이어의-수">히든레이어의 수</h2>
<p>은닉층이 하나인 MLP여도 뉴런개수 충분하면 복잡한 함수를 모델링 할 수 있다. </p>
<p>하지만 복잡한 문제에서는 심층신경망이 더 좋음</p>
<p>훨씬 적은 양의 뉴런을 사용하므로 성능올라감</p>
<p>과적합 전까지 은닉층 개수 늘린다.</p>
<p>층 증가할수록 뉴런 개수는 줄인다.</p>
<p>그러나 데이터셋에 대해 같은 뉴런수를 쓰기도 하고, 첫번째 층의 뉴런을 다른 것 들보다 아주 키우기도 한다</p>
<p>실전에서 조기정지, 정규화사용하고, stretch pants (늘릴만큼 늘리고 점차줄이는 방법) 사용 </p>
<ol>
<li>병목현상 막기</li>
<li>한 층이 너무 적은 뉴런을 가지면 충분한 표현력을 갖지 못한다. </li>
</ol>
<h2 id="학습률">학습률</h2>
<p>최적 파라미터는 최대학습률/2이다.</p>
<p>점진적으로 매우 큰 학습률까지 키워본 다음 수백번 반복해 학습</p>
<p>처음에는 학습률의 손실이 줄어들지만 점차 는다 → 늘어나기 직전이 최적 파라미터</p>
<h2 id="배치사이즈">배치사이즈</h2>
<p>매우 큰 배치는</p>
<ol>
<li>GPU같은 하드웨어 가속기를 효율적으로 사용</li>
<li>초당 많은 샘플 처리 가능</li>
</ol>
<p>but</p>
<ol>
<li>훈련 초기 불안정한 훈련</li>
<li>좋지 못한 일반화 성능</li>
</ol>
<p>→ <strong>학습률 예열 방법</strong> 쓰면 됨 </p>
<p>→ <strong>램에 맞는 최대배치 사이즈 쓰면 됨</strong></p>
<h2 id="활성함수-반복-수">활성함수, 반복 수</h2>
<p>활성함수</p>
<ul>
<li>일반적으로 은닉층은 ReLU</li>
</ul>
<p>반복횟수(에포크)</p>
<ul>
<li>일반적으로 사용필요 없음</li>
<li>조기종료로 사용(대치가능)</li>
</ul>
<p>하이퍼파라미터를 수정하는 경우 다른 하이퍼 파라미터를 업데이트 해야한다. </p>
<p>최적의 학습률은 다른 파라미터에 의존적이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Feature Demention]]></title>
            <link>https://velog.io/@do_genie/Feature-Demention</link>
            <guid>https://velog.io/@do_genie/Feature-Demention</guid>
            <pubDate>Sat, 02 Dec 2023 11:43:09 GMT</pubDate>
            <description><![CDATA[<h2 id="차원의-저주">차원의 저주</h2>
<p>: 샘플 차원이 커지면 커질수록 해당 데이터를 잘 대변하지 못함을 말한다.  (샘플 밀도가 너무 낮아짐)</p>
<ul>
<li>새로운 인스턴스 넣었을 때 주변 인스턴스가 넘 떨어져있어 그 인스턴스 설명 불가능</li>
<li>오차 커질 수 있음</li>
<li>데이터가 주변에 너무 없어서 과도하게 다른 인스턴스와 연결해 설명이 안됨</li>
</ul>
<h3 id="해결방법">해결방법</h3>
<ol>
<li>샘플밀도가 높아질때 까지 Training set의 크기를 키우는 방법 → 아주 많은 데이터가 필요하다(기하급수적으로 feature 수 증가)
너무 차원크면 채워넣는 것도 의미 없음</li>
<li>차원축소 진행 (하지만 데이터가 일부 손실되기 때문에 미리 원본으로 돌려보고 진행하는 것을 추천)</li>
</ol>
<h2 id="차원축소">차원축소</h2>
<p><strong>장점</strong></p>
<ol>
<li>계산비용 줄어든다</li>
<li>차원이 줄어들기 때문에 시각화가 가능하다.</li>
<li>노이즈와 불필요한 디테일이 사라져 좋은 결과를 낸다</li>
</ol>
<p><strong>단점</strong></p>
<ol>
<li>정보손실 우려</li>
<li>파이프라인을 복잡하게 만들 수 있다. </li>
</ol>
<h3 id="차원축소의-방법">차원축소의 방법</h3>
<ol>
<li>투영방법 → 고차원을 저차원 공간에 투영하는 방법
하지만 항상 좋은 것은 아니다 → swiss roll(매니폴드)과 같은 형태는 데이터 형태를 잘 표현하지 못하는 경우가 있다. </li>
<li>PCA → 주성분 분석
subspace(초평면)로 축소하여 투영한다. 
분산이 최대로 보존되는 것이 목표이며 이러한 반영 축(초평면)을 C라고 한다. 
가장 큰 분산을 갖는 축 순서로 제1, 2, 3주성분이라고 한다.
이는 특이값 분해로 정할 수 있다. U(시그마)V^T (여기서 V가 축의 집합)
주성분 분석을 하기 전에 데이터들은 모두 원점(중심화)에 있어야 한다. </li>
</ol>
<p>X_d = XW_d 이고, W_d는 V의 d열이다. (d개만 뽑아 축소할 수 있다)</p>
<p>X_d는 축소된 행렬을 말한다. </p>
<p>만약 2개의 주성분을 썼는데 98%의 설명력을 가진다면, 나머지 남은 주성분들이 2%를 설명하는 것과 같음</p>
<h3 id="올바른-차원의-수-고르기">올바른 차원의 수 고르기</h3>
<p>그래프를 그려 찾을 수 있다. → PCA 주성분에 따른 설명력 그래프  (차원에 따른 분산을 그래프로 그린 것)</p>
<p>기울기 급감하는 부분이 최적의 주성분 개수이다. </p>
<h2 id="재구성오차reconstruction-errror">재구성오차(reconstruction errror)</h2>
<p>차원을 줄여 재구성했을 때 발생하는 오차를 말한다. </p>
<p>이미 손실 된 데이터는 줄이고자 했던 주성분의 역행렬을 곱해주면 다시 돌릴수있다. </p>
<p>svd_solver를 randomized로 설정하면 확률적 알고리즘을 사용해 처음 d개의 주성분의 근사값을 찾는다. </p>
<p>줄일 차원이 원래 차원보다 작으면 (많이 줄여야하면) 기본값보다 randomized가 빠르다. </p>
<p>반대라면 full svd가 낫다. </p>
<p>강제로 full svd로 바꿀수도 있음</p>
<h2 id="incremental-pca-점진적-주성분분석">Incremental PCA (점진적 주성분분석)</h2>
<p>기존 PCA문제: 전체 훈련셋을 메모리에 올려야 한다. </p>
<p>그러나 점진적 주성분분석은 훈련 데이터셋을 mini batch로 나누어 PCA알고리즘에 하나씩 주입한다. </p>
<p>→ 데이터셋이 클 때 유용하다. </p>
<p>fit 대신 Partial_fit()을 사용해야 한다. </p>
<p>Numpy memmap 사용하며 fit() 사용 가능 (메모리문제 피하기 가능)</p>
<h2 id="kernel-pca">kernel PCA</h2>
<p>Kernel trick 사용한 주성분 분석</p>
<p>KPCA : 비선형 투영이 가능하다 (매니폴드와 같은)</p>
<ul>
<li>투영 후 샘플 군집을 유지한다.</li>
<li>매니폴드 펼칠때 사용한다.</li>
<li>사용할 커널을 정할 수 있다 (차원 늘리기용)</li>
</ul>
<p>Linear, RBF, Sigmoid 사용 가능 (목적에 따라 다름)</p>
<p><strong>주로 커널 PCA는 비지도학습이지만 지도학습의 전처리과정으로도 사용 가능하다.</strong> </p>
<p>그리드 서치 사용해 최적의 파라미터값과 커널을 찾을 수 있음</p>
<ol>
<li>커널PCA로 차원 줄이기</li>
<li>로지스틱 회귀(분류)를 사용하기 </li>
</ol>
<p><strong>커널 선택하고 파라미터 튜닝하기</strong></p>
<ul>
<li>가장 낮은 재구성오차를 갖도록 하이퍼파라미터와 커널을 선택한다.</li>
<li>커널트릭을 사용하면 나타나는 피처맵은 무한차원 가진 특성공간에 옮겨지고, linear PCA사용해 2차원으로 축소된다.</li>
<li>재구성 포인트에 가장 가깝게 매핑된 포인트를 찾은 뒤 다시 특성공간에 놓은 것(재구성한 것)을  pre-image라고 한다.</li>
<li>pre-image 찾으면 여기서 재구성 오차 가장 적게 하는 커널, 파라미터 찾는다.</li>
</ul>
<p><strong>재구성 과정</strong></p>
<p>프로젝션 된 인스턴스를 트레이닝셋으로, 오리지널 인스턴스를 타겟으로 하여 지도학습 회귀모델을 훈련시킨다. </p>
<p>에러가 작으면 작을수록 좋다. </p>
<p>MSE가 가장 작은 커널과 하이퍼파라미터로 설정하는 것이 좋다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 정규화]]></title>
            <link>https://velog.io/@do_genie/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EA%B7%9C%ED%99%94</link>
            <guid>https://velog.io/@do_genie/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EA%B7%9C%ED%99%94</guid>
            <pubDate>Sat, 02 Dec 2023 09:43:08 GMT</pubDate>
            <description><![CDATA[<p>데이터 정규화는 데이터의 스케일을 조정하여 모델의 학습을 개선하고 예측 성능을 향상시키는 과정이다. 
주로 머신러닝 모델에서 사용된다. </p>
<h1 id="min-max-scaling-최소-최대-스케일링">Min-Max Scaling (최소-최대 스케일링):</h1>
<p>데이터를 특정 범위로 스케일링합니다. 일반적으로 0과 1 사이의 범위로 변환된다.</p>
<p>$$
X_{norm} = \frac {X-X_{min}}{X_{max} - X_{min}}
$$</p>
<p>$X$는 원래 데이터 포인트, $X_{min}$은 데이터의 최솟값, $X_{max}$는 데이터의 최댓값</p>
<pre><code class="language-python">from sklearn.preprocessing import MinMaxScaler

# 예시 데이터
data = {&#39;feature1&#39;: [-1, -0.5, 0, 1],
        &#39;feature2&#39;: [2, 6, 10, 18]}

df = pd.DataFrame(data)

# MinMaxScaler 객체 생성
scaler = MinMaxScaler()

# 데이터 변환 (fit과 transform을 한 번에 수행)
scaled_data = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

print(&quot;원본 데이터:&quot;)
print(df)

print(&quot;\nMinMax Scaling 후 데이터:&quot;)
print(scaled_data)
</code></pre>
<p>fit_transform 메서드를 사용해 변환된 데이터 얻는다.
참고로, 스케일러 객체를 사용하여 변환하는 것이 일반적이며, 새로운 데이터에 대해 스케일을 조정하려면 fit_transform 대신 fit 메서드를 먼저 호출한 다음 transform 메서드를 사용할 수 있다.</p>
<h1 id="standardization-표준화">Standardization (표준화)</h1>
<p>데이터를 평균이 0이고 표준편차가 1인 분포로 변환한다.</p>
<p>$$ 
X_{std} = \frac {X-μ}{σ}
$$</p>
<p>$X$는 원래 데이터 포인트, $μ$는 데이터의 평균, $σ$는 데이터의 표준편차</p>
<pre><code class="language-python">from sklearn.preprocessing import StandardScaler

# 예시 데이터프레임
data = {&#39;feature1&#39;: [-1, -0.5, 0, 1],
        &#39;feature2&#39;: [2, 6, 10, 18]}

df = pd.DataFrame(data)

# StandardScaler 객체 생성
scaler = StandardScaler()

# 데이터프레임의 열을 표준화
standardized_df = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

print(&quot;원본 데이터:&quot;)
print(df)

print(&quot;\n표준화 후 데이터:&quot;)
print(standardized_data)
</code></pre>
<h1 id="robust-scaling-로버스트-스케일링">Robust Scaling (로버스트 스케일링)</h1>
<p>중앙값과 사분위 범위를 사용해 이상치의 영향을 최소화</p>
<p>$$
X_{robust} = \frac {X-median}{IQR}
$$</p>
<pre><code class="language-python">from sklearn.preprocessing import RobustScaler

# 예시 데이터
data = {&#39;feature1&#39;: [-1, -0.5, 0, 1],
        &#39;feature2&#39;: [2, 6, 10, 18]}
df = pd.DataFrame(data)

# RobustScaler 객체 생성
scaler = RobustScaler()

# 데이터 변환 (fit과 transform을 한 번에 수행)
robust_scaled_data = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

print(&quot;원본 데이터:&quot;)
print(df)

print(&quot;\n로버스트 스케일링 후 데이터:&quot;)
print(robust_scaled_data)
</code></pre>
<p>로버스트 스케일링은 이상치에 영향을 받지 않고 스케일링을 수행하므로, 이상치가 있는 데이터셋에 유용하다.</p>
<h1 id="normalization-정규화">Normalization (정규화)</h1>
<p>각 데이터 포인트를 해당 벡터의 길이로 나누어 벡터를 단위 길이로 만든다. 
주로 특징 벡터를 정규화한다.데이터의 방향(각도)이 중요할 때 유용하다. </p>
<p>$$ 
X_{norm} = \frac{X}{∥X∥}
$$</p>
<pre><code class="language-python">from sklearn.preprocessing import Normalizer

# 예시 데이터
data = {&#39;feature1&#39;: [-1, -0.5, 0, 1],
        &#39;feature2&#39;: [2, 6, 10, 18]}
df = pd.DataFrame(data)

# Normalizer 객체 생성
normalizer = Normalizer()

# 데이터 변환 (fit과 transform을 한 번에 수행)
normalized_data = pd.DataFrame(normalizer.fit_transform(df), columns=df.columns)

print(&quot;원본 데이터:&quot;)
print(df)

print(&quot;\n정규화 후 데이터:&quot;)
print(normalized_data)
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Feature Selection]]></title>
            <link>https://velog.io/@do_genie/Feature-Selection</link>
            <guid>https://velog.io/@do_genie/Feature-Selection</guid>
            <pubDate>Fri, 01 Dec 2023 12:18:23 GMT</pubDate>
            <description><![CDATA[<p>Feature selection은 모델의 성능을 향상시키고 모델의 복잡도를 줄이기 위해 중요한 특성만을 선택하는 과정이다. </p>
<p>Feature selection에는 여러가지 알고리즘이 있다. </p>
<h3 id="상관관계-기반-선택">상관관계 기반 선택</h3>
<p>목표 변수와 각 특성 간의 상관관계를 계산하여 중요 특성을 선택한다. 특성간 다중공선성을 고려해 상관성 높은 특성중 하나를 선택한다. 
상관계수가 높을수록 두 변수 간의 선형적인 관계가 강하다고 판단한다. </p>
<pre><code class="language-python">import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 상관계수 계산
correlation_matrix = df.corr()

# 목표 변수와의 상관계수 확인 (여기에서는 간단하게 마지막 열을 목표 변수로 설정)
target_correlation = correlation_matrix[&#39;target&#39;]

# 상관계수의 절댓값이 높은 특성 선택 (예: 0.2 이상)
selected_features = target_correlation[abs(target_correlation) &gt; 0.2].index

# 선택된 특성 확인
print(&quot;Selected Features:&quot;, selected_features)</code></pre>
<p>절댓값이 0.2보다 큰 상관계수를 가진 특성을 선택하는 예시이다. </p>
<h4 id="일반적으로">일반적으로</h4>
<p>0.0 ~ 0.19: 거의 무시됨
0.20 ~ 0.39: 매우 약한 상관관계
0.40 ~ 0.59: 약한 상관관계
0.60 ~ 0.79: 중간 정도의 상관관계
0.80 ~ 1.0: 강한 상관관계
특정 문제나 데이터에 따라 적합한 임계값이 다를 수 있다. </p>
<h3 id="filter-methods-필터-방법">Filter Methods (필터 방법):</h3>
<p>Filter Methods에서는 특성과 타겟 간의 통계적인 관계를 기반으로 특성을 선택한다. 주로 분산이 낮거나 높은 특성, 상관관계가 낮은 특성 등을 제거하여 모델의 복잡도를 줄이는 데 기여한다.</p>
<h4 id="분산-기준-variance-threshold">분산 기준 (Variance Threshold):</h4>
<p>분산이 낮은 특성은 정보를 거의 제공하지 않을 가능성이 높다. 따라서 분산이 낮은 특성을 제거하여 모델의 복잡도를 줄일 수 있다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.feature_selection import VarianceThreshold
from sklearn.datasets import load_iris

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 분산 기준을 사용하여 특성 선택
threshold = 0.2  # 분산이 이 값보다 낮은 특성을 제거
selector = VarianceThreshold(threshold=threshold)
X_selected = selector.fit_transform(X)

# 선택된 특성 확인
selected_features = df.columns[selector.get_support()]
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_selected, columns=selected_features)
df_selected[&#39;target&#39;] = y

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())</code></pre>
<h4 id="상관관계-기준-correlation-threshold">상관관계 기준 (Correlation Threshold):</h4>
<p>특성 간의 상관관계가 높은 경우, 중복된 정보를 포함할 가능성이 높다. 특성 간의 상관관계가 높은 경우 하나의 특성만을 선택하여 다중공선성을 감소시킬 수 있다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 상관관계 기준을 사용하여 특성 선택
num_features_to_select = 2  # 선택할 특성의 수
selector = SelectKBest(score_func=f_classif, k=num_features_to_select)
X_selected = selector.fit_transform(X, y)

# 선택된 특성 확인
selected_features = df.columns[selector.get_support()]
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_selected, columns=selected_features)
df_selected[&#39;target&#39;] = y

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())
</code></pre>
<h4 id="카이제곱-검정-chi-square-test">카이제곱 검정 (Chi-Square Test):</h4>
<p>범주형 변수와 이산형 타겟 간의 독립성을 검정하여 특성을 선택한다. 이는 범주형 데이터에서 유용하게 활용된다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 카이제곱검정을 사용하여 특성 선택
num_features_to_select = 2  # 선택할 특성의 수
selector = SelectKBest(score_func=chi2, k=num_features_to_select)
X_selected = selector.fit_transform(X, y)

# 선택된 특성 확인
selected_features = df.columns[selector.get_support()]
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_selected, columns=selected_features)
df_selected[&#39;target&#39;] = y

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())
</code></pre>
<h4 id="상호정보량-mutual-information">상호정보량 (Mutual Information):</h4>
<p>특성과 타겟 간의 상호 정보량을 측정하여 중요한 특성을 선택한다. 상호 정보량은 두 변수 간의 의존성을 측정하는 지표로 사용된다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import mutual_info_classif

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 상호정보량을 사용하여 특성 선택
num_features_to_select = 2  # 선택할 특성의 수
selector = SelectKBest(score_func=mutual_info_classif, k=num_features_to_select)
X_selected = selector.fit_transform(X, y)

# 선택된 특성 확인
selected_features = df.columns[selector.get_support()]
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_selected, columns=selected_features)
df_selected[&#39;target&#39;] = y

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())
</code></pre>
<p>score_func 매개변수에는 사용할 통계적 검정 방법을 설정하며, 여기서는 상호정보량에 적합한 mutual_info_classif를 사용</p>
<h4 id="일원분산분석-anova">일원분산분석 (ANOVA):</h4>
<p>수치형 특성과 범주형 타겟 간의 분산 차이를 검정하여 유의미한 특성을 선택한다. 주로 회귀와 분류 문제에서 사용된다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# ANOVA를 사용하여 특성 선택
num_features_to_select = 2  # 선택할 특성의 수
selector = SelectKBest(score_func=f_classif, k=num_features_to_select)
X_selected = selector.fit_transform(X, y)

# 선택된 특성 확인
selected_features = df.columns[selector.get_support()]
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_selected, columns=selected_features)
df_selected[&#39;target&#39;] = y

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())</code></pre>
<p> score_func 매개변수에는 사용할 통계적 검정 방법을 설정하며, 여기서는 분류 문제에 적합한 f_classif를 사용</p>
<h4 id="통계적-검정-방법">통계적 검정 방법:</h4>
<p>다양한 통계적 검정 방법을 활용하여 특성과 타겟 간의 유의미한 차이를 검정하고 선택하는 방법이다. t-검정, F-검정 등이 여기에 속한다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from scipy.stats import ttest_ind

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# t-검정을 사용하여 특성 선택
num_features_to_select = 2  # 선택할 특성의 수
selected_features = []

for column in df.columns[:-1]:  # 마지막 열은 타겟 변수이므로 제외
    t_stat, p_value = ttest_ind(df[df[&#39;target&#39;] == 0][column], df[df[&#39;target&#39;] == 1][column])
    # 여기에서는 두 클래스 간의 t-검정을 수행했습니다. 실제로는 데이터의 클래스 수와 특성에 따라 다르게 조정해야 합니다.

    if p_value &lt; 0.05:  # 유의수준 0.05를 기준으로 선택
        selected_features.append(column)

# 선택된 특성 출력
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = df[selected_features + [&#39;target&#39;]]

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())</code></pre>
<p>t-검정을 기준으로 특성을 선택하는 방법
해당 특성의 두 클래스 간의 t-검정을 수행한 후, 유의수준을 기준으로 선택 여부를 결정</p>
<h3 id="wrapper-methods-래퍼-방법">Wrapper Methods (래퍼 방법):</h3>
<p>Wrapper Methods는 모델의 성능을 기반으로 특성을 선택한다. 주로 전방 선택법(Forward Selection), 후방 제거법(Backward Elimination), 순차적 특성 선택법(Sequential Feature Selection) 등이 사용되며, 이들 방법은 반복적으로 모델을 학습하여 특성을 선택한다.</p>
<h4 id="전방-선택법-forward-selection">전방 선택법 (Forward Selection)</h4>
<p>:  특성을 하나씩 추가하면서 모델의 성능을 평가하고 최적의 특성 조합을 찾는 방법</p>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 전방 선택법을 사용하여 특성 선택
selected_features = []
best_accuracy = 0.0
remaining_features = list(range(X.shape[1]))

while remaining_features:
    best_feature = None
    for feature in remaining_features:
        # 현재까지 선택된 특성에 현재 특성을 추가
        candidate_features = selected_features + [feature]

        # 모델 학습 및 성능 평가
        model = RandomForestClassifier(random_state=42)
        model.fit(X_train.iloc[:, candidate_features], y_train)
        y_pred = model.predict(X_test.iloc[:, candidate_features])
        accuracy = accuracy_score(y_test, y_pred)

        # 최고 정확도를 갖는 특성 업데이트
        if accuracy &gt; best_accuracy:
            best_accuracy = accuracy
            best_feature = feature

    # 선택된 특성에 추가하고 후보 목록에서 제거
    selected_features.append(best_feature)
    remaining_features.remove(best_feature)

# 선택된 특성 출력
print(&quot;Selected Features:&quot;, selected_features)</code></pre>
<p>해당 코드에서는 랜덤 포레스트 분류기를 이용하여 각 단계에서 특성을 선택하고 모델의 성능을 평가한다. 최고의 정확도를 갖는 특성을 선택하며, 이를 반복하여 최적의 특성 조합을 찾는다.</p>
<h4 id="후방-제거법-backward-elimination">후방 제거법 (Backward Elimination)</h4>
<p>: 모든 특성을 포함한 모델에서 시작하여 가장 덜 유용한 특성을 하나씩 제거하면서 모델의 성능을 평가</p>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 후방 제거법을 사용하여 특성 선택
selected_features = list(range(X.shape[1]))

while len(selected_features) &gt; 1:
    worst_feature = None
    for feature in selected_features:
        # 현재까지 선택된 특성에서 현재 특성을 제외
        candidate_features = [f for f in selected_features if f != feature]

        # 모델 학습 및 성능 평가
        model = RandomForestClassifier(random_state=42)
        model.fit(X_train[:, candidate_features], y_train)
        y_pred = model.predict(X_test[:, candidate_features])
        accuracy = accuracy_score(y_test, y_pred)

        # 현재까지 최저 정확도를 갖는 특성 업데이트
        if worst_feature is None or accuracy &lt; worst_accuracy:
            worst_accuracy = accuracy
            worst_feature = feature

    # 선택된 특성에서 최저 정확도를 갖는 특성을 제외
    selected_features.remove(worst_feature)

# 선택된 특성 출력
print(&quot;Selected Features:&quot;, selected_features)</code></pre>
<p>랜덤 포레스트 분류기를 이용하여 각 단계에서 특성을 제외하면서 모델의 성능을 평가한다. 최저 정확도를 갖는 특성을 제외하면서 최적의 특성 조합을 찾는다.</p>
<h4 id="순차적-특성-선택법-sequential-feature-selection">순차적 특성 선택법 (Sequential Feature Selection)</h4>
<p>: 전방선택법(Forward Selection)이나 후방제거법(Backward Elimination)과 유사하지만, 각 단계에서 특성을 추가하거나 제거할 때 모델의 성능이 가장 크게 향상되는 특성을 선택한다. mlxtend 라이브러리를 사용한다. </p>
<pre><code class="language-python">pip install mlxtend

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from mlxtend.feature_selection import SequentialFeatureSelector

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 랜덤 포레스트 분류기를 사용한 순차적 특성 선택법
model = RandomForestClassifier(random_state=42)
sfs = SequentialFeatureSelector(model,
                                k_features=&#39;best&#39;,  # 선택할 특성의 개수 (여기서는 최적의 개수를 선택)
                                forward=True,  # True면 전방선택법, False면 후방제거법
                                floating=False,
                                scoring=&#39;accuracy&#39;,  # 성능 평가 지표
                                cv=5)  # 교차 검증의 폴드 수

sfs.fit(X_train, y_train)

# 선택된 특성 출력
selected_features = list(sfs.k_feature_idx_)
print(&quot;Selected Features:&quot;, selected_features)

# 선택된 특성을 포함한 데이터프레임 생성
df_selected = pd.DataFrame(X_train[:, selected_features], columns=[f&#39;feature_{i}&#39; for i in selected_features])
df_selected[&#39;target&#39;] = y_train

# 선택된 특성을 포함한 데이터프레임 출력
print(&quot;\nDataFrame with Selected Features:&quot;)
print(df_selected.head())
</code></pre>
<p>SequentialFeatureSelector를 사용하여 랜덤 포레스트 분류기를 이용한 순차적 특성 선택법을 구현한다. 최적의 특성 개수를 선택하도록 설정하고, 전방선택법을 사용하고 있다.</p>
<h3 id="embedded-methods-내장-방법">Embedded Methods (내장 방법):</h3>
<p>Embedded Methods에서는 모델 학습 과정에서 특성 선택이 이루어진다. 일부 모델은 학습 중에 특성의 중요도를 평가하고, 중요하지 않은 특성을 제외하도록 설계되어 있다. 예를 들어, LASSO(L1 정규화)와 같은 방법이 해당된다.</p>
<h3 id="pca-principal-component-analysis">PCA (Principal Component Analysis):</h3>
<p>PCA는 데이터의 차원을 축소하고 주성분을 선택하여 새로운 특성 공간으로 매핑하는 방법이다. 주로 차원 축소를 목적으로 사용되지만, 중요한 특성만을 선택함으로써 모델의 복잡도를 줄이는 역할도 한다.</p>
<pre><code class="language-python">import pandas as pd
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터프레임 생성
df = pd.DataFrame(X, columns=iris.feature_names)
df[&#39;target&#39;] = y

# 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# PCA를 사용하여 특성 선택
n_components = 2  # 선택할 주성분의 개수
pca = PCA(n_components=n_components)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)

# 주성분 선택 결과 출력
print(f&quot;Selected Principal Components: {pca.components_}&quot;)

# 선택된 주성분으로 랜덤 포레스트 모델 학습
model = RandomForestClassifier(random_state=42)
model.fit(X_train_pca, y_train)

# 테스트 세트로 모델 평가
y_pred = model.predict(X_test_pca)
accuracy = accuracy_score(y_test, y_pred)
print(f&quot;Accuracy with PCA-selected features: {accuracy}&quot;)</code></pre>
<h3 id="tree-based-methods">Tree-based Methods:</h3>
<p>Tree-based methods를 사용한 특성 선택은 주로 특성의 중요도(Feature Importance)를 기반으로 이루어진다. Tree-based methods에서 각 특성의 중요도를 평가할 수 있기 때문에, 중요한 특성들을 선택하여 모델을 훈련시키는 방법을 말한다.</p>
<p>여러 트리 기반의 알고리즘에서 특성의 중요도는 각 트리에서 분할 기준을 선택할 때 해당 특성이 얼마나 영향을 미치는지를 나타낸다. 중요도는 주로 불순도(impurity) 감소나 정보 이득(information gain)과 관련된 지표로 측정된다.</p>
<p>가장 대표적인 트리 기반 알고리즘은 랜덤 포레스트(Random Forest)와 Gradient Boosting 계열이다.</p>
<h4 id="랜덤포레스트-random-forest">랜덤포레스트 (random forest)</h4>
<ul>
<li>랜덤 포레스트는 여러 결정 트리를 앙상블하여 생성된다.</li>
<li>각 트리는 부트스트랩 샘플링을 통해 생성되고, 각 노드에서 최적의 분할 기준을 찾을 때 무작위로 선택된 특성 부분 집합을 고려한다.</li>
<li>각 트리에서 특성의 중요도를 측정하고, 이를 기반으로 전체 랜덤 포레스트의 특성 중요도를 평균하여 얻을 수 있다.</li>
<li>중요도가 낮은 특성은 제외할 수 있다.</li>
<li>해당 모델에서 제공하는 특성 중요도를 활용하여 진행된다. <pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import numpy as np
</code></pre>
</li>
</ul>
<h1 id="가상의-데이터셋을-사용-iris-데이터셋">가상의 데이터셋을 사용 (iris 데이터셋)</h1>
<p>iris = load_iris()
X = iris.data
y = iris.target</p>
<h1 id="데이터를-훈련-세트와-테스트-세트로-나눔">데이터를 훈련 세트와 테스트 세트로 나눔</h1>
<p>X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)</p>
<h1 id="랜덤-포레스트-모델-생성-및-학습">랜덤 포레스트 모델 생성 및 학습</h1>
<p>rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)</p>
<h1 id="특성-중요도-확인">특성 중요도 확인</h1>
<p>feature_importances = rf_model.feature_importances_
print(&quot;Feature Importances:&quot;, feature_importances)</p>
<h1 id="중요도가-높은-순서대로-특성의-인덱스를-정렬">중요도가 높은 순서대로 특성의 인덱스를 정렬</h1>
<p>sorted_feature_indices = np.argsort(feature_importances)[::-1]</p>
<h1 id="상위-k개의-특성-선택-예-상위-2개의-특성-선택">상위 k개의 특성 선택 (예: 상위 2개의 특성 선택)</h1>
<p>top_k = 2
selected_features = sorted_feature_indices[:top_k]
print(f&quot;Selected Features (Top {top_k}):&quot;, selected_features)</p>
<pre><code>feature_importances_ 속성을 통해 각 특성의 중요도를 확인하고, 중요도가 높은 순서대로 특성의 인덱스를 정렬하여 상위 k개의 특성을 선택한다.


#### Gradient Boosting 계열 (XGBoost, LightGBM)
- Gradient Boosting 계열 역시 각 트리가 순차적으로 생성되며, 이전 트리의 예측 오차를 보완하는 방식으로 동작한다.
- 각 트리에서의 특성 중요도를 측정하고, 중요도가 낮은 특성은 제외할 수 있다.
- XGBoost

```python
from sklearn.datasets import load_iris
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
import numpy as np

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# XGBoost 모델 생성 및 학습
xgb_model = XGBClassifier(random_state=42)
xgb_model.fit(X_train, y_train)

# 특성 중요도 확인
feature_importances = xgb_model.feature_importances_
print(&quot;Feature Importances:&quot;, feature_importances)

# 중요도가 높은 순서대로 특성의 인덱스를 정렬
sorted_feature_indices = np.argsort(feature_importances)[::-1]

# 상위 k개의 특성 선택 (예: 상위 2개의 특성 선택)
top_k = 2
selected_features = sorted_feature_indices[:top_k]
print(f&quot;Selected Features (Top {top_k}):&quot;, selected_features)
</code></pre><p>feature_importances_ 속성을 통해 각 특성의 중요도를 확인하고, 중요도가 높은 순서대로 특성의 인덱스를 정렬하여 상위 k개의 특성을 선택한다.</p>
<ul>
<li>LightGBM<pre><code class="language-python"></code></pre>
</li>
</ul>
<h1 id="lightgbm-모델-생성">LightGBM 모델 생성</h1>
<p>params = {&#39;objective&#39;: &#39;binary&#39;, &#39;metric&#39;: &#39;binary_logloss&#39;, &#39;boosting_type&#39;: &#39;gbdt&#39;}
train_data = lgb.Dataset(X_train, label=y_train)
model = lgb.train(params, train_data, num_boost_round=100)</p>
<h1 id="특성-중요도-시각화">특성 중요도 시각화</h1>
<p>lgb.plot_importance(model, figsize=(10, 6), title=&#39;Feature Importance&#39;)</p>
<h1 id="중요도가-낮은-특성-제거">중요도가 낮은 특성 제거</h1>
<p>threshold = 50  # 예를 들어, 중요도 상위 50개의 특성만 선택
selected_features = [feature for i, feature in enumerate(X_train.columns) if i in model.feature_importance().argsort()[-threshold:]]
X_train_selected = X_train[selected_features]
X_test_selected = X_test[selected_features]</p>
<h1 id="새로운-모델-생성-및-평가">새로운 모델 생성 및 평가</h1>
<p>train_data_selected = lgb.Dataset(X_train_selected, label=y_train)
model_selected = lgb.train(params, train_data_selected, num_boost_round=100)
y_pred = model_selected.predict(X_test_selected)
y_pred_binary = (y_pred &gt; 0.5).astype(int)
accuracy = accuracy_score(y_test, y_pred_binary)</p>
<p>print(f&quot;Accuracy with selected features: {accuracy}&quot;)</p>
<pre><code>
#### _피처 중요도 확인_
- 각 트리 기반 알고리즘에서 피처 중요도는 모델의 feature_importances_ 속성을 통해 확인할 수 있습니다.
- 중요도가 높은 특성은 해당 모델에서 예측에 큰 영향을 미치는 특성으로 간주됩니다.

#### _특성 선택 방법_
- 특성 중요도를 기반으로 한 특성 선택은 일정 임계값 이상의 중요도를 가진 특성을 선택하는 방식이 일반적입니다.
- 사용자가 지정한 임계값 이하의 중요도를 가진 특성들을 제거하여 모델을 구성할 수 있습니다.

### Regularization (정규화):

일부 선형 모델은 L1 또는 L2 정규화를 통해 특성의 가중치를 조절한다. 주로 선형회귀 모델에 많이 사용된다. 모델의 복잡도를 제어해 가중치를 축소하는 방법으로 Ridge 와 Lasso방법이 있다. L1 정규화(LASSO)는 일부 특성의 가중치를 0으로 만들어 특성 선택 효과를 낸다.

Lasso 회귀를 사용한 방법은 다음과 같다. 
```python
from sklearn.datasets import load_iris
from sklearn.linear_model import Lasso
from sklearn.model_selection import train_test_split
import numpy as np

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 라쏘 회귀 모델 생성 및 학습
alpha = 0.1  # 정규화 강도를 조절하는 매개변수 (0.1은 예시로 조절 필요)
lasso_model = Lasso(alpha=alpha, random_state=42)
lasso_model.fit(X_train, y_train)

# 특성의 가중치 확인
feature_weights = lasso_model.coef_
print(&quot;Feature Weights:&quot;, feature_weights)

# 가중치가 0이 아닌 특성 선택
selected_features = np.where(feature_weights != 0)[0]
print(&quot;Selected Features:&quot;, selected_features)</code></pre><p>coef_ 속성을 통해 특성의 가중치를 확인하고, 가중치가 0이 아닌 특성을 선택한다. 라쏘 회귀는 L1 정규화를 사용하며, 가중치가 0이 되는 특성이 생기므로 특성 선택 효과를 갖는다.</p>
<p>Ridge 회귀를 사용한 특성 선택은 주로 L2 정규화를 통해 특성의 가중치를 제어하여 수행된다. Ridge 회귀는 L2 정규화 항을 포함하고 있어, 가중치의 크기를 제한함으로써 모델의 복잡도를 조절한다.</p>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
import numpy as np

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Ridge 회귀 모델 생성 및 학습
alpha = 0.1  # 정규화 강도를 조절하는 매개변수 (0.1은 예시로 조절 필요)
ridge_model = Ridge(alpha=alpha, random_state=42)
ridge_model.fit(X_train, y_train)

# 특성의 가중치 확인
feature_weights = ridge_model.coef_
print(&quot;Feature Weights:&quot;, feature_weights)

# 가중치가 0이 아닌 특성 선택
selected_features = np.where(feature_weights != 0)[0]
print(&quot;Selected Features:&quot;, selected_features)
</code></pre>
<p>coef_ 속성을 통해 특성의 가중치를 확인하고, 가중치가 0이 아닌 특성을 선택한다.</p>
<h3 id="recursive-feature-elimination-rfe">Recursive Feature Elimination (RFE):</h3>
<p>RFE는 모델을 반복적으로 학습시켜 가장 중요하지 않은 특성을 제거하는 방법으로, 모델 성능이 가장 좋아지는 특성의 개수를 찾을 수 있다. 
주로 RFE는 선형 모델과 함께 사용되며, 각 반복에서 중요하지 않은 특성들을 제거한다. </p>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# 가상의 데이터셋을 사용 (iris 데이터셋)
iris = load_iris()
X = iris.data
y = iris.target

# 데이터를 훈련 세트와 테스트 세트로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 선형 회귀 모델 생성
model = LinearRegression()

# RFE를 사용하여 특성 선택 (예: 2개의 특성 선택)
num_features_to_select = 2
rfe = RFE(model, n_features_to_select=num_features_to_select)
X_train_rfe = rfe.fit_transform(X_train, y_train)

# 선택된 특성 확인
selected_features = [i for i, selected in enumerate(rfe.support_) if selected]
print(&quot;Selected Features:&quot;, selected_features)</code></pre>
<p>n_features_to_select 매개변수를 통해 선택할 특성의 개수를 조절할 수 있다. 선택된 특성은 rfe.support_ 속성을 통해 확인할 수 있다.</p>
<h2 id="이진분류-문제에서-feature-selection">이진분류 문제에서 feature selection</h2>
<ol>
<li>필터 방법</li>
<li>REF</li>
<li>Tree-based methods</li>
<li>Regularization -&gt; L1 정규화 (Lasso)</li>
</ol>
<h2 id="선형회귀-문제에서-feature-selection">선형회귀 문제에서 feature selection</h2>
<ol>
<li>REF</li>
<li>래퍼 방법</li>
<li>Regularization -&gt; L1 정규화 (Lasso)</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>