<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>saepal_cse.log</title>
        <link>https://velog.io/</link>
        <description>친해져요</description>
        <lastBuildDate>Fri, 22 Nov 2024 12:57:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. saepal_cse.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/saepal_cse" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Ch08.이미지를 위한 인공 신경망]]></title>
            <link>https://velog.io/@saepal_cse/Ch08.%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9D%B8%EA%B3%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D</link>
            <guid>https://velog.io/@saepal_cse/Ch08.%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9D%B8%EA%B3%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D</guid>
            <pubDate>Fri, 22 Nov 2024 12:57:55 GMT</pubDate>
            <description><![CDATA[<h1 id="합성곱-신경망의-구성-요소">합성곱 신경망의 구성 요소</h1>
<h2 id="합성곱-convolution">합성곱 convolution</h2>
<p>영어로 Convolution은 &#39;대단히 복잡한 것, 난해한 것, 얽히고 설킨 것&#39;이라고 한다.
합성곱이란 두 함수를 서로 곱해서 합한다는 뜻이다.</p>
<h3 id="합성곱-vs-밀집층">합성곱 vs 밀집층</h3>
<p>밀집층이 입력데이터 <strong>전체</strong>에 뉴런의 가중치를 곱하고 절편을 더해서 1개의 출력을 만드는 반면, 합성곱은 <strong>일부</strong>에 가중치를 곱하고 절편을 더해서 1개의 출력을 만든다.</p>
<h3 id="합성곱-신경망-convolutional-neural-network-cnn">합성곱 신경망 convolutional neural network, CNN</h3>
<p>합성곱을 이용한 신경망. 이는마치입력데이터위를 이동하면서같은도장(!)으로하나씩찍는것처럼생각할수있습니다. 도장을찍을때마다출력이하나씩만들어지는거죠. 완전 연결 신경망(밀집층 신경망)과 반대의 의미이다! 밀집층과 다르게 2차원 입력에 용이하다. 
filter: 뉴런
kernel: 뉴런</p>
<p>눈치챘을까? filter = kernel = neuron 다 같은 말이다.
다만 우리끼리 비밀스럽게,<img src="https://velog.velcdn.com/images/saepal_cse/post/20341064-456f-441d-9b60-8b596a26e04a/image.png" alt=""></p>
<p>뉴런 개수: <strong>필터</strong>
입력에 곱해지는 가중치: <strong>커널</strong>
이라고 불러보자.</p>
<p>그리고 <strong>특성맵 feature map</strong>은 합성곱 계산을 통해 얻은 출력을 의미한다!
<img src="https://velog.velcdn.com/images/saepal_cse/post/dc1fe325-bd52-4e5d-b807-d446bd5236d3/image.png" alt="">
(4,4)의 크기의 입력을 (2,2)의 출력으로 줄인 느낌이 난다. 신기하다...</p>
<h2 id="케라스-합성곱-층">케라스 합성곱 층</h2>
<pre><code class="language-python">from tensorflow import keras
keras.layers.Conv2d(10, kernel_size(3,3), activation=&#39;relu&#39;)</code></pre>
<p>keras.layers 패키지 아래에는 여러 케라스의 층들을 구현할 수 있는 클래스가 있다. 합성곱 층은 Conv2D 클래스에서 제공된다.
kernel_size는 필터에 사용된 커널의 크기; 보통 (3,3), (5,5) 추천
활성화 함수는 렐루를 써본다.</p>
<h3 id="합성곱-신경망">합성곱 신경망</h3>
<p>헷갈리지 말것!</p>
<blockquote>
<p> 합성곱 층이 단 한 개만 있어도 합성곱 신경망이다!</p>
</blockquote>
<h3 id="패딩과-스트라이드">패딩과 스트라이드</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/638f4133-71aa-4e32-9f24-d8a98d1a1351/image.png" alt="">
<strong>padding</strong>: 입력 배열 주위를 가상의 원소로 채우는 것
<strong>same padding</strong>: (4,4) 입력을 (4,4) 출력으로 만들고 싶을 때 0처럼 의미없는 값을 주변에 둘러싸주는 것. 필터(도장) 찍을 횟수를 늘려주는 의의를 가진다.
<strong>valid padding</strong>: 패딩 없이 순수 입력만을 쓰는 경우. <del>솔직히 이런건 패딩이라고 이름 붙이면 안되지 않은가?</del>, 라고 생각했지만 파라미터 기본값을 valid라고 주기 때문에 이해되었다.</p>
<h3 id="풀링-pooling">풀링 pooling</h3>
<ul>
<li>특성맵 크기 줄이기</li>
<li>최대 풀링과 평균 풀링이 있다. 가중치가 없기 때문에 최대값과 평균값을 output으로 내어놓는 것이다.<img src="blob:https://velog.io/8c03ac8b-a41b-4979-86a3-14df529e0637" alt="업로드중..">
<code>keras.layers.MaxPooling2D(2)</code>
2칸을 스트라이드로 해서 이동하겠다는 뜻임. 즉 특성맵 크기를 반으로 줄인다는 뜻.</li>
</ul>
<blockquote>
<p>기억하자! 1. 풀링은 가로세로 방향으로만 진행된다. 2. 특성 맵의 개수는 변하지 않는다
풀링을사용하는이유는합성곱에서스트라이드를크게하여특성맵을줄이는것보다 풀링 층에서크
기를줄이는것이경험적으로더나은성능을내기때문입니다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴공과에 와서 배운 점]]></title>
            <link>https://velog.io/@saepal_cse/%EC%BB%B4%EA%B3%B5%EA%B3%BC%EC%97%90-%EC%99%80%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EC%A0%90</link>
            <guid>https://velog.io/@saepal_cse/%EC%BB%B4%EA%B3%B5%EA%B3%BC%EC%97%90-%EC%99%80%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EC%A0%90</guid>
            <pubDate>Tue, 19 Nov 2024 03:29:51 GMT</pubDate>
            <description><![CDATA[<p>누군가 내게 컴공과에 와서 배운 점이 무엇이냐고 묻는다면, 참 여러가지가 있겠으나 한번 정리해보고 싶어서 회고록을 쓴다. 아직 2학년 2학기임을 참고해주시길...</p>
<h3 id="일단-읽어보자는-마인드가-생겼다">일단 읽어보자는 마인드가 생겼다</h3>
<p>대학교에 와서 그런지, 컴공과에 와서 그런지는 몰라도 (아니면 둘 다일지도) 개념이 산발적이고 해야하는 공부는 더더욱 산발적이었다. 체계 있게 1타 강사가 가르쳐주는 떠먹임지식은 전혀 없었다는 말이다.</p>
<p>덕분에 나는 매주 주어지는 2~3개 정도의 과제에 매번 새로움의 연속을 느꼈고 솔직히 말하자면 요즘도 자괴감을 많이 겪고 있다. 매번 나의 무능함에, 더욱이 나보다 잘하는 사람은 늘 많기 때문이다...</p>
<p>그러나 덕분에 일단 읽어보자는 마인드가 생겼다.</p>
<p>나의 친구 챗지피티가 있어서 나는 챗지피티한테 모르겠는 개념을 하나씩 물어가면서 문장을 번역하는 듯하게 읽어보자 부터 시작한다.</p>
<p>그러다 보면 100퍼센트 이해는 무리여도 과제를 풀어볼 정도까지는 이해를 해볼 수 있었다. 전에는 모르는 문제만 보면 정신이 나가서 펜부터 끄적인다거나 코딩부터 해보는 기이한 습관이 있었지만 요즘에는 그러한 것들이 많이 줄어들고 팔짱을 끼고 차분하게 고민해보는 그런 생소한 습관이 자라나고 있다...</p>
<p>긍정적 발전인듯!</p>
<h3 id="모임-주도-경험이-늘고-있다">모임 주도 경험이 늘고 있다</h3>
<p>컴공과만 그런지는 몰라도 유난히 스터디!가 많다.
거의 한 학기에 하나 이상의 스터디를 하고 있으며 심지어 내가 여는 경우도 많다.</p>
<p>덕분에 나는 모임의 운영 경험 팁?이 좀 늘고 있는 듯하다. 몇 가지 예시를 들자면 이렇다.</p>
<ul>
<li>모임장은 모임원을 따듯하게 품어주나 확실한 비전이 있어야 한다.</li>
<li>모임원들의 구성은 성실하고 배울 점이 있으면 좋으니 뽑을 수 있다면 이런 특징인 사람을 뽑는 게 좋다.</li>
<li>장소는 고정적인게 좋다.</li>
</ul>
<p>특히 따뜻하게 품어주는 행동을 해야 자괴감 상실, 모임원 이탈 등의 상황이 생기지 않고 다들 소속감과 자기효능감을 느끼기 좋다는 건, 정말 정말 새겨야 한다!</p>
<p>일단 지금 생각나는 건 이  정도인데 더욱 생각해보면 나올 것 같다.
이상 마무리~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch07 ]]></title>
            <link>https://velog.io/@saepal_cse/Ch07</link>
            <guid>https://velog.io/@saepal_cse/Ch07</guid>
            <pubDate>Tue, 12 Nov 2024 10:20:36 GMT</pubDate>
            <description><![CDATA[<h2 id="패션-mnist">패션 MNIST</h2>
<p>딥러닝에서 MNIST가 유명함 -&gt; 손으로 쓴 0~9까지 숫자 자료. 패션 MNIST는 숫자 대신 패션 아이템으로 이루어짐</p>
<pre><code>from tensorflow import keras

(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()</code></pre><p>60,000개의 28*28 이미지로 되어 있음</p>
<pre><code>print(train_input.shape, train_target.shape)
print(test_input.shape, test_target.shape)</code></pre><p>(60000, 28, 28) (60000,)
(10000, 28, 28) (10000,)</p>
<pre><code>import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 10, figsize=(10,10))
for i in range(10):
    axs[i].imshow(train_input[i], cmap=&#39;gray_r&#39;)
    axs[i].axis(&#39;off&#39;)
plt.show()</code></pre><p><img src="https://velog.velcdn.com/images/saepal_cse/post/153fa5a7-73f8-4f60-8ee9-9cbc99e6ef0b/image.png" alt=""></p>
<h2 id="로지스틱-회귀로-패션-아이템-분류하기">로지스틱 회귀로 패션 아이템 분류하기</h2>
<p>훈련 샘플이 6만개라 전체를 한꺼번에 하기보다는 하나씩 꺼내서 모델을 훈련하는 것이 좋다.
이럴 때 사용하는 것이 확률적 경사 하강법(SGDClassifier).</p>
<pre><code>train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
print(train_scaled.shape)</code></pre><p>(60000, 784)
train_scaled = train_input / 255.0 
이 부분이 중요한데, 각 pixel이 0<del>255의 정수값을 가지는 값이다. 머신러닝에서 효율적으로 사용하기 위해 이 값을 0</del>1사이의 실수로 변경하여 정규화 시켜준다. 이를 위해 최대값으로 나누는 작업을 한다</p>
<pre><code>from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier

sc = SGDClassifier(loss=&#39;log&#39;, max_iter=5, random_state=42)

scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)
print(np.mean(scores[&#39;test_score&#39;]))</code></pre><p>0.8195666666666668
max_iter=5는 SGDClassifier 반복 횟수</p>
<h2 id="인공신경망">인공신경망</h2>
<p><a href="https://velog.velcdn.com/images/saepal_cse/post/d460c506-9b66-41dc-9fe0-76fed5ef3f99/image.png"></a></p>
<h3 id="텐서플로와-케라스">텐서플로와 케라스</h3>
<pre><code>import tensorflow as tf
from tensorflow import keras</code></pre><h3 id="인공신경망으로-모델-만들기">인공신경망으로 모델 만들기</h3>
<pre><code>from sklearn.model_selection import train_test_split

train_scaled, val_scaled, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)

print(train_scaled.shape, train_target.shape)
print(val_scaled.shape, val_target.shape)</code></pre><p>(48000, 784) (48000,)
(12000, 784) (12000,)</p>
<pre><code>dense = keras.layers.Dense(10, activation=&#39;softmax&#39;, input_shape=(784,))
model = keras.Sequential(dense)
</code></pre><h3 id="인공신경망으로-패션-아이템-분류하기">인공신경망으로 패션 아이템 분류하기</h3>
<pre><code>model.compile(loss=&#39;sparse_categorical_crossentropy&#39;, metrics=&#39;accuracy&#39;)
print(train_target[:10])</code></pre><p>[7 3 5 8 6 9 3 3 9 9]</p>
<pre><code>model.fit(train_scaled, train_target, epochs=5)</code></pre><p>결과가 할 때마다 다르게 나온다. 그러나 충분히 안정적으로 된다면 차이가 크지 않다.</p>
<pre><code>model.evaluate(val_scaled, val_target)</code></pre><h2 id="심층-신경망">심층 신경망</h2>
<h3 id="2개의-층">2개의 층</h3>
<ul>
<li>케라스 API를 사용하여 패션 MNIST 데이터셋을 불러옴</li>
<li>입력층과 출력층 사이에 밀집층이 추가되었음</li>
<li>입력층과 출력층 사이에 있는 모든 층을 은닉층이라고 부름<h3 id="심층-신경망-만들기">심층 신경망 만들기</h3>
</li>
<li>dense1과 dense2 객체를 Sequential 클래스를 추가하여 심층 신경망을 생성<pre><code>model = keras.Sequential([dense1, dense2])</code></pre></li>
<li>summary를 통해 층에 대한 유용한 정보를 얻을 수 있음
(None, 100)
None : 샘플의 개수 →아직 정의되지 않아 None으로 출력됨
100 : 은닉층의 뉴런 개수
param 78500
샘플마다 784개의 픽셀값이 은닉층을 통과하면서 100개의 특성으로 압축됨
784 * 100 + 100 (절편)</li>
</ul>
<h3 id="층을-추가하는-다른-방법">층을 추가하는 다른 방법</h3>
<p>Sequential 클래스의 생성자 안에서 바로 Dense 클래스의 객체를 만드는 경우
편리하지만 아주 많은 층을 추가하려면 Sequential 클래스 생성자가 매우 길어짐
Sequential 클래스의 객체를 만들고 이 객체의 add() 메서드를 호출하여 층을 추가함
<img src="https://velog.velcdn.com/images/saepal_cse/post/25398a72-c242-472c-a243-0aaa328ddc4c/image.png" alt=""></p>
<h3 id="렐루-함수">렐루 함수</h3>
<p>층이 많은 심층 신경망일수록 그 효과가 누적되어 학습을 더 어렵게 만드는데 이를 개선하기 위한 활성화 함수
이미지 분류 모델의 은닉층에 많이 사용
Flatten 클래스 사용하여 층 추가</p>
<ul>
<li>배치 차원을 제외하고 나머지 입력 차원을 모두 일렬로 펼치는 역할</li>
<li>입력에 곱해지는 가충치나 절편이 없음 → 인공 신경망 성능을 위해 기여하는 바는 없음</li>
</ul>
<h3 id="옵티마이저permalink">옵티마이저Permalink</h3>
<p>신경망의 가중치와 절편을 학습하기 위한 알고리즘 또는 방법
가장 기본적인 옵티마이저는 확률적 경사 하강법인 SGD임
SGD 옵티마이저를 사용하려면 compile() 메서드의 optimizer 매개변수를 ‘sgd’로 지정함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch06 비지도 학습]]></title>
            <link>https://velog.io/@saepal_cse/Ch06-%EB%B9%84%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5-k5hyqvcc</link>
            <guid>https://velog.io/@saepal_cse/Ch06-%EB%B9%84%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5-k5hyqvcc</guid>
            <pubDate>Tue, 12 Nov 2024 09:54:33 GMT</pubDate>
            <description><![CDATA[<h2 id="06-1-군집-알고리즘">06-1 군집 알고리즘</h2>
<p>비지도 학습, Unsupervised Learning은 가장 큰 특징이 타겟 데이터가 없다. 현실 세계에서 라벨 작업을 하거나 타겟까지 있는 데이터를 구하는 것은 쉬운 일이 아니어서 점점 비지도 학습의 중요성이 증가하고 있으며 최근 나온 ChatGPT도 비지도학습을 이용한 대표적 사례라 할 수 있다.</p>
<h2 id="06-2-k-평균">06-2 k-평균</h2>
<p>K-평균 알고리즘의 경우 랜덤하게 클러스터 개수를 정해서 시작한다. 여기에서 클러스터 수 , 즉 K값을 몇개로 하는 것이 가장 좋을까 하는 문제가 발생한다. 적절한 K값을 찾기 위해 엘보우(Elbow) 방법을 사용한다. inertia값과 클러스터 개수의 그래프를 그려서 그 그래프의 변곡점이 생기는(마치 엘보우 처럼 보이는 위치)위치에서 최적의 K값을 결정한다.</p>
<h2 id="06-3-주성분-분석pca">06-3 주성분 분석(PCA)</h2>
<p>주성분 분석은 특성값이 너무 많은 경우 차원 축소를 위해 사용하는 방법이다. </p>
<p>Kaggle에서 대표적인 비지도 학습 데이터 Set : Fruits-360 
<a href="https://www.kaggle.com/datasets/moltean/fruits">https://www.kaggle.com/datasets/moltean/fruits</a></p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/fe0155ff-7765-438a-bb5c-77072f04ef7b/image.png" alt=""></p>
<pre><code>apple_mean=np.mean(apple,axis=0).reshape(100,100)
pineapple_mean=np.mean(pineapple,axis=0).reshape(100,100)
banana_mean=np.mean(banana,axis=0).reshape(100,100)
fig,axs=plt.subplots(1,3,figsize=(20,5))
axs[0].imshow(apple_mean,cmap=&#39;gray_r&#39;)
axs[1].imshow(pineapple_mean,cmap=&#39;gray_r&#39;)
axs[2].imshow(banana_mean,cmap=&#39;gray_r&#39;)
plt.show()</code></pre><p>왼쪽부터 사과, 파인애플, 바나나.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch05. 트리 알고리즘]]></title>
            <link>https://velog.io/@saepal_cse/ch05-%ED%8A%B8%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@saepal_cse/ch05-%ED%8A%B8%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Tue, 05 Nov 2024 12:18:49 GMT</pubDate>
            <description><![CDATA[<h1 id="결정트리">결정트리</h1>
<p><strong>1. 데이터 불러오기</strong></p>
<pre><code class="language-python">import pandas as pd
wine = pd.read_csv(&#39;https://bit.ly/wine_csv_data&#39;)</code></pre>
<p><strong>2. 데이터 확인 및 전처리</strong></p>
<ul>
<li>데이터셋에 대한 정보를 출력하고, 누락된 값이 있는지 확인합니다. 누락된 값이 있을 경우, 처리 방법에 대해 언급하고, 데이터를 넘파이 배열로 변환합니다.</li>
</ul>
<p>*<em>판다스 데이터프레임의 유용한 메서드 2개
*</em></p>
<p>*<em>info()
*</em>    </p>
<ul>
<li>이 메서드는 데이터프레임의 각 열의 데이터 타입과 누락된 데이터가 있는지 확인하는데 유용합니다.</li>
</ul>
<p>*<em>describe()
*</em>    </p>
<ul>
<li>이 메서드는 열에 대한 간략한 통계를 출력해 줍니다. 최소, 최대, 평균값 등을 볼 수 있습니다</li>
</ul>
<pre><code class="language-python">data = wine[[&#39;alcohol&#39;, &#39;sugar&#39;, &#39;pH&#39; ]].to_numpy()
target = wine[&#39;class&#39;].to_numpy()</code></pre>
<p>훈련 세트와 테스트 세트로 나눕니다 </p>
<pre><code class="language-python">from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)</code></pre>
<p><strong>3. 데이터 표준화</strong></p>
<ul>
<li>데이터를 표준화하기 위해 StandardScaler를 사용하여 특성을 변환합니다. 이 작업은 훈련 세트와 테스트 세트에 모두 적용되어야 합니다.</li>
</ul>
<pre><code class="language-python">from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)</code></pre>
<p><strong>4. 로지스틱 회귀 모델 훈련</strong></p>
<ul>
<li>표준화된 데이터를 사용하여 로지스틱 회귀 모델을 훈련합니다.</li>
</ul>
<pre><code class="language-python">from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_scaled, train_target)</code></pre>
<p>훈련된 모델의 성능을 훈련 세트와 테스트 세트에서 평가합니다.</p>
<blockquote>
<p>결정 트리 모델은 데이터를 스무고개처럼 질문을 통해 분류하며, 데이터를 잘 나눌 수 있는 질문을 찾아가며 정확도를 높입니다. 
사이킷런의 <strong>DecisionTreeClassifier 클래스</strong>를 사용하여 결정 트리 모델을 훈련합니다. </p>
</blockquote>
<ul>
<li>이때, random_state 매개변수를 지정하는 이유는 결정 트리 알고리즘에서 노드에서 최적 분할을 찾기 전에 특성 순서를 무작위로 섞는데, 이로 인해 실행할 때마다 결과가 조금씩 다를 수 있기 때문입니다. 노드의 순서를 일정하게 유지하기 위해 random_state를 설정합니다.</li>
</ul>
<p><strong>5. 결정 트리 모델 훈련</strong></p>
<ul>
<li>결정 트리 모델을 훈련하기 위해 DecisionTreeClassifier를 사용합니다.</li>
</ul>
<pre><code class="language-python">from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(train_scaled, train_target)</code></pre>
<p>결정 트리 모델의 훈련 세트와 테스트 세트에서의 성능을 평가합니다.</p>
<p><strong>6. 결정 트리 시각화</strong></p>
<p>결정 트리를 시각화하기 위해 plot_tree() 함수를 사용합니다</p>
<pre><code class="language-python">import matplotlib.pyplot as plt
from sklearn.tree import plot_tree

plt.figure(figsize=(10,7))
plot_tree(dt, max_depth=1, filled=True, feature_names=[&#39;alcohol&#39;, &#39;sugar&#39;, &#39;pH&#39;])
plt.show()</code></pre>
<p>밑 결과를 통해 트리의 구조 및 각 노드에서 수행되는 분류 기준을 시각적으로 파악할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/soheean1370/post/23f8dcfa-9033-4fb6-8e6b-c49ba63026f2/image.png" alt=""></p>
<blockquote>
<p>결정 트리 모델은 노드와 가지로 구성되며, 노드에서 특정 조건을 검사하고 그 결과에 따라 가지를 따라 이동합니다. 일반적으로 하나의 노드는 2개의 가지를 가지게 됨</p>
</blockquote>
<p>노드(node) - 특성에 대한 테스트를 수행</p>
<ul>
<li>루트 노드(root node)는 맨 위에 위치하며, 리프 노드(leaf node)는 트리의 맨 아래에 위치합니다</li>
</ul>
<p>가지(branch) - 테스트 결과를 나타냄</p>
<hr>
<p><strong>트리의 시각화</strong></p>
<p>결정 트리를 시각화하려면 plot_tree() 함수를 사용할 수 있습니다. 이 함수를 통해 트리의 깊이를 제한하고, 노드의 색을 클래스에 따라 칠할 수 있습니다. 또한 feature_names 매개변수를 사용하여 특성의 이름을 표시할 수 있습니다.</p>
<pre><code class="language-python">plt.figure(figsize=(10, 7))
plot_tree(dt, max_depth=1, filled=True, feature_names=[&#39;alcohol&#39;, &#39;sugar&#39;, &#39;pH&#39;])
plt.show()</code></pre>
<p><img src="https://velog.velcdn.com/images/soheean1370/post/8366cdd3-7219-4b9e-8457-ee7cf43453e9/image.png" alt=""></p>
<h3 id="불순도">불순도</h3>
<p>결정 트리에서 노드를 나누는 기준은 불순도입니다. 불순도는 노드의 클래스 분포의 혼잡도를 나타내며, 주요한 기준으로는 지니 불순도(Gini impurity)와 엔트로피 불순도(Entropy impurity)가 있습니다.</p>
<ul>
<li><p>지니 불순도(Gini impurity): 클래스 비율의 제곱을 더한 다음 1에서 뺀 값으로 계산됩니다. 결정 트리의 기본 불순도 지표입니다.</p>
</li>
<li><p>엔트로피 불순도(Entropy impurity): 클래스 비율을 밑이 2인 로그로 곱하여 계산합니다.</p>
</li>
</ul>
<p>불순도의 차이를 계산하여 정보 이득(Information Gain)을 최대화하기 위해 데이터를 분할합니다. 정보 이득은 부모 노드와 자식 노드 간의 불순도 차이로 정의됩니다.</p>
<blockquote>
<p>결정 트리는 데이터를 분할하기 위해 불순도를 기준으로 사용하며, 정보 이득을 최대화하도록 노드를 분할합니다. 이를 시각화하여 노드의 특성과 클래스 분포를 살펴볼 수 있습니다.</p>
</blockquote>
<h3 id="가지치기">가지치기</h3>
<p>가지치기는 결정 트리에서 모델의 일반화 성능을 향상시키기 위한 중요한 기술입니다. 결정 트리의 가지치기는 트리의 최대 깊이를 제한하여 모델을 더 간결하게 만드는 방법 중 하나입니다. 이를 통해 훈련 세트에 과적합되는 것을 방지할 수 있습니다.</p>
<pre><code class="language-python">dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_scaled, train_target)
</code></pre>
<ul>
<li>가지치기 후 모델의 성능은 훈련 세트에서는 낮아질 수 있지만 테스트 세트에서는 더 좋은 성능을 얻을 수 있습니다. 이것을 일반화라고 합니다.</li>
</ul>
<pre><code class="language-python">import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(20,15))
plot_tree(dt, filled=True, feature_names=[&#39;alcohol&#39;, &#39;sugar&#39;, &#39;pH&#39;])
plt.show()</code></pre>
<p><img src="https://velog.velcdn.com/images/soheean1370/post/5a4b124b-1cc5-4c97-84ad-e1384e21342f/image.png" alt=""></p>
<p>이를 통해 루트 노드부터 리프 노드까지의 경로를 시각적으로 확인할 수 있습니다.</p>
<p><strong>특성 중요도</strong>
결정 트리 모델은 각 특성의 중요도를 계산해줍니다. 특성 중요도는 각 노드의 정보 이득과 전체 샘플에 대한 비율을 곱한 후 특성별로 더하여 계산합니다. 중요도는 트리 노드에서 분기하는 결정에 특성이 얼마나 기여하는지를 나타냅니다.</p>
<pre><code class="language-python">print(dt.feature_importances_)</code></pre>
<p>특성 중요도를 통해 어떤 특성이 모델에서 가장 유용한 역할을 하는지 확인할 수 있으며, 이를 통해 특성 선택에 활용할 수 있습니다. </p>
<hr>
<h1 id="교차-검증과-그리드-서치">교차 검증과 그리드 서치</h1>
<h3 id="검증-세트validation-set">검증 세트(Validation Set)</h3>
<ul>
<li>데이터 세트를 학습 세트와 검증 세트, 테스트 세트로 나누어 테스트 세트에 과적합한 모델이될 가능성을 낮출 수 있습니다</li>
</ul>
<p>훈련 세트의 입력 데이터와 타깃 데이터를 train_input과 train_target배열에 저장하고  </p>
<p>그 다음 train_input과 train_target을 다시 train_test_split() 함수에 넣어 훈련 세트 sub_input, sub_target과 검증 세트 val_input, val_target을 만듭니다.</p>
<pre><code class="language-python">from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)

sub_input, val_input, sub_target, val_target = train_test_split(train_input, train_target, test_size=0.2, random_state=42)</code></pre>
<pre><code class="language-python">dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)
print(dt.score(sub_input, sub_target))
print(dt.score(val_input, val_target))</code></pre>
<blockquote>
<p>검증 세트의 성능을 평가하고 모델이 과대적합되었다면, 매개변수를 조정하여 더 나은 모델을 찾을 수 있습니다. 
반복적으로 모델을 훈련하고 검증 세트를 사용하여 성능을 평가하며 매개변수를 조정합니다.</p>
</blockquote>
<h3 id="교차-검증cross-validation">교차 검증(Cross Validation)</h3>
<ul>
<li>모델의 성능을 안정적으로 평가하고 최적의 매개변수를 찾는 데 도움이 되는 기술</li>
</ul>
<p><strong>역할</strong></p>
<ul>
<li>검증 세트를 나누는 과정에서 훈련 세트의 크기가 감소하는 문제를 극복하고 모델의 안정적인 성능 평가를 가능하게 합니다.</li>
<li>모델의 성능을 여러 번 측정하여 평균을 계산해 최종 성능을 얻습니다.</li>
</ul>
<p><strong>종류</strong></p>
<ul>
<li>3-폴드, 5-폴드, 10-폴드 교차 검증 등 여러 종류가 있으며, 보통 5-폴드나 10-폴드 교차 검증을 많이 사용합니다.</li>
</ul>
<p><strong>사이킷런의 교차 검증 함수</strong></p>
<ul>
<li><strong>cross_validate()</strong> 함수를 사용하여 교차 검증을 수행할 수 있습니다.</li>
<li><strong>cross_val_score()</strong> 함수는 cross_validate() 함수의 결과 중 test_score 값만 반환합니다.</li>
</ul>
<pre><code class="language-python">from sklearn.model_selection import cross_validate
from sklearn.model_selection import StratifiedKFold
from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(random_state=42)

scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())
print(np.mean(scores[&#39;test_score&#39;]))</code></pre>
<p>교차 검증에서 훈련 세트를 섞지 않고 사용하려면 기본적으로 StratifiedKFold(분류 모델) 또는 KFold(회귀 모델)를 사용합니다.</p>
<p>k-폴드 교차 검증 (k-fold cross validation)</p>
<ul>
<li>훈련 세트를 k 부분으로 나눠서 교차 검증을 수행하는 것.</li>
</ul>
<p>훈련 세트를 섞어서 사용하려면 분할기(splitter)를 지정해야 합니다.</p>
<pre><code class="language-python">from sklearn.model_selection import KFold
scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())

splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)

scores = cross_validate(dt, train_input, train_target, cv=splitter)

print(np.mean(scores[&#39;test_score&#39;]))</code></pre>
<h3 id="하이퍼파라미터-튜닝">하이퍼파라미터 튜닝</h3>
<blockquote>
<p><strong>모델 파라미터:</strong> 머신러닝 모델이 학습하는 파라미터
<strong>파라미터(parameter, 매개변수):</strong> 학습 과정에서 생성되는 변수
<strong>하이퍼파라미터:</strong> 머신러닝 모델이 학습할 수 없어서 사용자가 지정해야만 하는 파라미터 (사람의 개입 없이 하이퍼파라미터를 자동으로 튜닝하는 기술을 &#39;<strong>AutoML</strong>&#39; 이라고 합니다)</p>
</blockquote>
<h4 id="그리드-서치-grid-search">그리드 서치 (Grid Search)</h4>
<ul>
<li>하이퍼파라미터 탐색을 자동화해 주는 도구</li>
<li>탐색과 교차 검증을 한 번에 수행</li>
</ul>
<ol>
<li>탐색할 매개변수를 지정합니다.</li>
<li>그리드 서치를 수행하여 최상의 평균 검증 점수가 나오는 매개변수 조합을 찾습니다.</li>
<li>그리드 서치는 최상의 매개변수에서 전체 훈련 세트를 사용해 최종 모델을 훈련합니다.</li>
<li>사이킷런의 GridSearchCV 클래스를 사용하면 그리드 서치를 간단히 수행할 수 있습니다. </li>
</ol>
<pre><code class="language-python">from sklearn.model_selection import GridSearchCV

params = {&#39;min_impurity_decrease&#39;: [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]}

gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(train_input, train_target)

dt = gs.best_estimator_
best_index = np.argmax(gs.cv_results_[&#39;mean_test_score&#39;])
print(gs.cv_results_[&#39;params&#39;][best_index])</code></pre>
<p>GridSearchCV 클래스를 사용하여 최적의 매개변수를 탐색하고, 최상의 매개변수, 모델, 및 교차 검증 점수를 얻을 수 있습니다.</p>
<h4 id="랜덤-서치-random-search">랜덤 서치 (Random Search)</h4>
<ul>
<li>연속적인 매개별수 값을 탐색할 때 유용</li>
<li>랜덤 서치에는 매개변수 값의 목록을 전달하는 것이 아니라 매개변수를 샘플링할 수 있는 확률 분포 객체를 전달</li>
</ul>
<p>가능한 모든 조합을 시도하는 대신 각 반복마다 하이퍼파라미터에 랜덤으로 대입하여 지정한 횟수만큼 평가.</p>
<p>먼저, SciPy 라이브러리에서 uniform과 randint 클래스를 임포트합니다. 이 두 클래스는 주어진 범위에서 값들을 균등하게 샘플링할 수 있습니다.</p>
<blockquote>
<p>싸이파이(scipy)는 어떤 라이브러리인가
    - 싸이파이는 파이썬의 핵심 과학 라이브러리 중 하나이다. 적분, 보간, 선형대수, 확률 등을 포함한 수치 계산 전용 라이브러리이다. 사이킷런은 넘파이와 싸이파이 기능을 많이 사용한다.</p>
</blockquote>
<pre><code class="language-python">from scipy.stats import uniform, randint</code></pre>
<p>uniform 클래스는 주어진 범위 내에서 실수 값을 샘플링하고, randint 클래스는 정수 값을 샘플링합니다. 예를 들어, 0에서 10 사이의 정수를 랜덤하게 샘플링해보겠습니다.</p>
<pre><code class="language-python">rgen = randint(0, 10)
samples = rgen.rvs(10)</code></pre>
<p>여기서 rvs 메서드는 지정한 횟수만큼 샘플링하여 배열로 반환합니다. 샘플링 결과는 무작위성에 따라 다를 수 있습니다.</p>
<p>uniform 클래스의 사용법도 동일하며, 0에서 1 사이의 실수를 샘플링해보겠습니다.</p>
<pre><code class="language-python">ugen = uniform(0, 1)
samples = ugen.rvs(10)</code></pre>
<p>샘플링 결과는 0과 1 사이의 임의의 실수입니다. 랜덤 서치는 이러한 확률 분포 객체를 활용하여 매개변수 값을 샘플링하고 교차 검증을 수행하여 최적의 매개변수 조합을 찾는 방식으로 동작합니다.</p>
<p>랜덤 서치의 사용</p>
<pre><code class="language-python">params = {
    &#39;min_impurity_decrease&#39;: uniform(0.0001, 0.001),
    &#39;max_depth&#39;: randint(20, 50),
    &#39;min_samples_split&#39;: randint(2, 25),
    &#39;min_samples_leaf&#39;: randint(1, 25),
}</code></pre>
<p>랜덤 서치를 설정한 매개변수와 샘플링 횟수를 이용하여 수행합니다.</p>
<pre><code class="language-python">from sklearn.model_selection import RandomizedSearchCV

rs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42), params, n_iter=100, n_jobs=-1, random_state=42)
rs.fit(train_input, train_target)</code></pre>
<p>랜덤 서치는 총 100번(n_iter 매개변수) 샘플링하여 교차 검증을 수행하고 최적의 매개변수 조합을 찾습니다. 결과를 확인하기 위해 최적의 매개변수와 교차 검증 점수를 출력합니다.</p>
<pre><code class="language-python">best_params = rs.best_params_
best_score = np.max(rs.cv_results_[&#39;mean_test_score&#39;])</code></pre>
<p>랜덤 서치는 랜덤하게 샘플링하기 때문에 실행할 때마다 결과가 조금씩 다를 수 있습니다.</p>
<hr>
<h1 id="트리의-앙상블">트리의 앙상블</h1>
<h4 id="정형-데이터structure-data">정형 데이터(structure data)</h4>
<ul>
<li>csv파일처럼 가지런히 정리되어 있는 데이터</li>
</ul>
<h4 id="비정형-데이터unstructured-data">비정형 데이터(unstructured data)</h4>
<ul>
<li>텍스트, 이미지, 영상, 음악 등 DB로 표현하기 어려운 데이터</li>
</ul>
<h4 id="앙상블-학습ensemble-learning">앙상블 학습(ensemble learning)</h4>
<ul>
<li>정형데이터에서 가장 뛰어난 알고리즘</li>
<li>결정트리를 기반</li>
</ul>
<h3 id="랜덤-포레스트-random-forest">랜덤 포레스트 (random forest)</h3>
<ul>
<li>각 트리를 훈련하기 위해 부트스트랩 방식으로 데이터를 생성하며, 이는 입력된 훈련 데이터에서 중복된 샘플을 허용하여 추출하는 방식</li>
<li>랜덤하게 선택한 샘플과 특성을 사용하기 때문에 훈련 세트에 과대적합되는 것을 막아주고 검증 세트와 테스트 세트에서 안정적인 성능을 얻을 수 있습니다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/soheean1370/post/c57c8a9a-3ebd-4427-9aa8-db0a1987d413/image.png" alt=""></p>
<h4 id="부트스트랩bootstrap">부트스트랩(bootstrap)</h4>
<ul>
<li>데이터 세트에서 중복을 허용하여 데이터를 샘플링하는 방식을 의미</li>
<li>1,000개의 샘플이 있을 때 먼저 1개를 뽑고, 다시 가방에 넣어 그다음 샘플을 뽑는 방식. 부트스트랩 샘플이란 결국 부트스트랩 방식으로 샘플링하여 분류한 데이터라는 의미!</li>
<li>OOB(Out Of Bag) 샘플
  -부트스트랩 샘플에 포함되지 않고 남는 샘플
  -이 샘플을 이용하여 부트스트랩 샘플로 훈련한 결정 트리 평가 가능.(검증 세트의 역할)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/soheean1370/post/f0997a18-8b52-4ea0-8def-898193c7e2ee/image.png" alt=""></p>
<pre><code class="language-python">rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate( rf, train_input, train_target,return_train_score=True, n_jobs=-1)</code></pre>
<p>객체를 생성하고 cross_validate()함수를 사용하여 교차 검증을 수행하였습니다.
훈련 세트와 검증 세트의 점수를 비교하면 과대적합을 파악하는데 용이합니다</p>
<pre><code class="language-python">rf = RandomForestClassifier(oob_score=True, n_jobs= -1, random_state=42)
rf.fit(train_input, train_target)</code></pre>
<p>RandomForestClassifier의 oob_score 매개변수를 활용하여 OOB (out of bag) 점수를 계산하였습니다.
OOB 점수를 사용하면 교차 검증을 대신할 수 있어서 결과적으로 훈련 세트에 더 많은 샘플을 사용할 수 있습니다.</p>
<h3 id="엑스트라-트리-extra-tree">엑스트라 트리 (Extra Tree)</h3>
<ul>
<li><p>랜덤 포레스트와 동일한 점.</p>
<ul>
<li>결정 트리가 제공하는 대부분의 매개변수를 지원함.</li>
<li>전체 특성 중 일부 특성을 랜덤하게 선택하여 노드를 분할하는데 사용함.</li>
<li>랜덤하게 노드 분할하기 때문에 계산속도가 빠름.</li>
</ul>
</li>
<li><p>랜덤 포레스트와 차이점.</p>
<ul>
<li>랜덤포레스트는 부트스트랩 샘플을 사용하는 반면, 엑스트라 트리는 부트스트랩 샘플을 사용하지 않음.</li>
<li>즉, 각 결정 트리를 만들 때 전체 훈련 세트를 사용함.</li>
<li>보통 엑스트라 트리가 무작위성이 좀 더 크기 때문에 랜덤 포레스트보다 더 많은 결정 트리를 훈련해야 함.</li>
</ul>
</li>
</ul>
<p><strong>랜덤 포레스트</strong></p>
<pre><code class="language-python">from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target,
                       return_train_score=True, n_jobs=-1)
print(np.mean(scores[&#39;train_score&#39;]), np.mean(scores[&#39;test_score&#39;]))</code></pre>
<blockquote>
<p>훈련 세트: 0.9973541965122431, 검증 세트: 0.8905151032797809</p>
</blockquote>
<p><strong>엑스트라 트리</strong></p>
<pre><code class="language-python">from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target,
                       return_train_score=True, n_jobs=-1)
print(np.mean(scores[&#39;train_score&#39;]), np.mean(scores[&#39;test_score&#39;]))</code></pre>
<blockquote>
<p>훈련 세트: 0.9974503966084433, 검증 세트: 0.8887848893166506</p>
</blockquote>
<p>랜덤 포레스트와 엑스트라 트리의 결과는 비슷하며, 데이터셋이 간단한 경우 큰 차이를 보이지 않습니다. 엑스트라 트리가 조금 더 무작위성이 크기 때문에 더 많은 결정 트리를 훈련해야 할 수 있습니다.</p>
<h3 id="그레이디언트-부스팅gradient-boosting">그레이디언트 부스팅(Gradient Boosting)</h3>
<ul>
<li>깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블하는 방법<ul>
<li>길이가 얕은 결정 트리를 사용하기에 <strong>과대적합에 강하고 일반적으로 높은 일반화 성능</strong>을 기대할 수 있음.</li>
</ul>
</li>
<li>default depth = 3 이며 결정트리 100개를 사용</li>
<li>경사하강법을 사용하여 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균제곱오차함수를 사용</li>
</ul>
<h4 id="subsample-매개변수">subsample 매개변수</h4>
<ul>
<li>그레이디언트 부스팅의 트리 훈련에 사용할 훈련 세트의 비율을 조절</li>
<li>이 매개변수의 기본값은 1.0으로 전체 훈련 세트를 사용</li>
<li>하지만 subsampled 1보다 작으면 훈련 세트의 일부를 사용. 마치 경사 하강법 단계마다 일부 샘플을 랜덤하게 선택하여 진행하는 확률적 경사 하강법이나 미니배치 경사 하강법과 비슷</li>
</ul>
<h3 id="히스토그램-기반-그레이디언트-부스팅-histogram-based-gradient-boosting">히스토그램 기반 그레이디언트 부스팅 (Histogram based Gradient Boosting)</h3>
<ul>
<li>정형 데이터를 다루는 머신러닝 알고리즘 중에서 가장 인기가 높은 알고리즘 중 하나</li>
<li>입력 특성을 256개의 구간으로 나누어 먼저 전처리를 진행함으로써 노드를 분할할 때 최적의 분할을 빠르게 찾을 수 있습니다</li>
<li>트리의 개수를 지정하는데 n_estimators 대신에 부스팅 반복 횟수를 지정하는 <strong>max_iter</strong>를 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch04. 다양한 분류 알고리즘]]></title>
            <link>https://velog.io/@saepal_cse/CH04-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80</link>
            <guid>https://velog.io/@saepal_cse/CH04-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80</guid>
            <pubDate>Tue, 29 Oct 2024 09:28:38 GMT</pubDate>
            <description><![CDATA[<h2 id="04-1-로지스틱-회귀">04-1 로지스틱 회귀</h2>
<h3 id="문제-배경-설명과-k-최근접-이웃-분류-알고리즘으로-접근">문제 배경 설명과 k-최근접 이웃 분류 알고리즘으로 접근</h3>
<p>생선의 (길이, 높이, 두께 ...등) 7가지 특성으로 이 생선이 어느 생선일지 확률을 구하는 문제를 가정해보자.
이전에 배웠던 k-최근접 이웃 분류 알고리즘에서, 이웃의 클래스를 알 수 있었다. 그렇기에 이웃의 클래스 비율을 확률이라고 가정하면? 문제가 매우 쉬워진다.</p>
<blockquote>
<p>csv파일은 판다스의 pd.read_csv(&#39;https...&#39;)로 받고 이것은 데이터프레임이다.
데이터프레임은 to_numpy() 함수로 넘파일 배열로 변경하여 sklearn에서 활용해야 한다.</p>
</blockquote>
<p>다음은 표준점수로 전처리하는 방법인데, 핵심은 # 훈련 세트의 통계 값으로 테스트 세트를 변환해야 한다. 기껏 훈련한 모델이 쓸모 없게 되므로! 전에 배웠던 건데 까먹어서 적으면서 기억하기!</p>
<pre><code class="language-python">from sklearn.preprocessing import StandardScaler

std = StandardScaler()
std.fit(X_train)
X_train_scaled = std.transform(X_train)
X_test_scaled = std.transform(X_test)
dtc.fit(X_train_scaled, y_train)
print(&#39;모델의 정확도 :&#39;, round(dtc.score(X_test_scaled, y_test), 4))</code></pre>
<p>그리고 주변 이웃의 비율에 따라 확률 구하는 함수는 다음과 같다.
<code>kn.predict_proba(test_data)</code></p>
<p>그러나, K-최근접 이웃 분류 알고리즘은 이웃의 개수가 3개, 4개, 등등 정해져있기에 1/3, 2/3, 3/3 확률 밖에 안나온다. 즉, 확률이라고 말하기 애~매하다.<img src="https://velog.velcdn.com/images/saepal_cse/post/a0e1fd3e-fb27-4698-960e-33332a6a575e/image.png" alt="predict_proba"></p>
<h3 id="로지스틱-회귀-알고리즘으로의-접근">로지스틱 회귀 알고리즘으로의 접근</h3>
<p>그래서 로지스틱 회귀 알고리즘으로 갈아탔다.
로지스틱 회귀: 선형 방정식을 사용한 분류 알고리즘. 선형 회귀랑 똑같이 선형 방정식을 활용하지만 분류 모델이다. 선형 회귀와 달리 시그모이드 함수나 소프트맥스 함수를 사용하여 클래스 확률을 출력할 수 있다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/40cb9c49-3dfb-415a-9657-459649ae5144/image.png" alt=""></p>
<h3 id="이진-분류부터-시작">이진 분류부터 시작</h3>
<p>시그모이드 함수란(또는 로지스틱 함수) 선형 방정식의 출력을 0과 1 사이 범위의 값으로 압축하며 이진(또는 더 많은) 분류를 위해 사용하는 함수이다. <code>spipy</code>라이브러리의 <code>expit(lr.decision_function(test_data))</code> 명령어를 통해 z값을 넣고 시그모이드 함숫값을 알 수 있다.
이진 분류라면 0.5 이상이면 1, 이하면 0으로 표현하여 확률을 0%에서 100%까지 나타낼 수 있는 것이다!</p>
<p><code>lr.predict_proba(test_data)</code> 훈련까지는 똑같고 확률 보기는 똑같은 메서드 써서 나타내면 이번에는 매우 잘 나온 확률을 확인해볼 수 있다! 이건 이진 분류의 예시.<img src="https://velog.velcdn.com/images/saepal_cse/post/a55c3257-e167-46c8-a313-4bdd253453ba/image.png" alt=""></p>
<h3 id="다중-분류로-마무리">다중 분류로 마무리</h3>
<p>다중분류로 바꾸려면?</p>
<blockquote>
<p>로지스틱 회귀 모델은 데이터를 보고 예측을 잘 할 수 있도록 &#39;학습&#39;을 하는데, 이 학습 과정에서 여러 번 반복을 거칩니다. 이 반복을 통해 모델이 예측을 잘하기 위한 &#39;최적의 값&#39;을 찾게 됩니다.
그런데 이 반복 횟수가 너무 적으면, 모델이 충분히 학습하지 못해서 예측이 정확하지 않게 됩니다. 지금 책에서 언급한 기본 반복 횟수는 100번인데, 이게 데이터의 복잡성에 비해 부족할 수 있어요. 그래서 100번만 반복했을 때 모델이 아직 최적의 상태에 도달하지 못했다는 &#39;경고&#39;가 뜨는 거예요.</p>
</blockquote>
<p>라는 chatgpt의 말처럼 max_iter를 1000으로 늘리고, </p>
<blockquote>
<p>규제를 해주는 이유: 과적합 방지
규제를 완화해주는 이유: 과소적합 방지</p>
</blockquote>
<p>이므로 규제를 완화 해준다.
해결 방법으로 반복 횟수를 더 늘려서(예를 들어 1000번으로) 모델이 충분히 학습할 시간을 주는 거죠.</p>
<p>소프트 맥스 함수는? 다중 분류에서의 시그모이드 함수(로지스틱 함수). 사용법은 <code>scipy</code> 라이브러리의 <code>softmax(lr.decision_function(test_data), axis=1)</code>이고 axis가 1이므로 각 행, 즉 각 샘플에 대한 소프트맥스를 계산하는 셈이다.</p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/7f41b78d-ef9e-44a9-a564-30cb4bcf6a71/image.png" alt=""></p>
<h2 id="04-2-확률적-경사-하강법-stochastic-gradient-descent">04-2 확률적 경사 하강법 Stochastic Gradient Descent</h2>
<p><strong>확률적 경사 하강법</strong>: 대표적인 점진적 학습이다. 샘플이 계속 추가될 때마다 최적의 모델을 위해 매번 새로운 학습을 하면 비효율적이므로 점진적 학습을 활용.
방법은 이렇다. 훈련 세트에서 샘플을 하나씩 꺼내 손실 함수의 경사를 따라 내려오며 최적의 모델을 찾는 것이다.</p>
<p>샘플을 하나씩 사용하지 않고 여러개를 사용하면 미니배치 경사 하강법이 됨. &lt;- 실전 활용
한번에 전체 샘플을 사용하면 배치경사 하강법이 됨.</p>
<p><strong>손실 함수</strong>: 확률적 경사 하강법이 최적화할 대상. 문제 별로 다른 손실함수가 정해져 있음. 미분가능해야한다. 왜냐면 확률적 경사 하강법에서는 기울기(변화량)을 통해 경사를 내려오기 때문이다.</p>
<ul>
<li>이진 분류 -&gt; 로지스틱 손실함수 = 이진 크로스엔트로피 손실 함수</li>
<li>다중 분류 -&gt; 크로스엔트로피 손실 함수</li>
<li>회귀 -&gt; 평균 제곱 오차</li>
</ul>
<p><strong>에포크</strong> : 확률적 경사 하강법에서 전체 샘플을 모두 사용하는 한 번 반복을 의미</p>
<p>잊지 말자!!!</p>
<blockquote>
<p>확률적경사하강법을꼭사용하는알고리즘이있습니다. 바로신경망알고리즘입니다. 신경망은일반적으로많은데이터 를사용하기때문에한번에모든데이터를사용하기어렵습니다. 또모델이매우복잡하기때문에수학적인방법으로해 답을얻기어렵습니다. 신경망모델이확률적경사하강법이나미니배치경사하강법을사용한다는점을꼭기억하세요.</p>
</blockquote>
<hr>
<p><strong>SGDClassifier로 점진적 학습을 위한 확률적 경사하강법 활용해보기</strong>
<code>sc = SGDClassifier(loss=&#39;log&#39;, max_iter=100, tol=None)</code>에서 <code>tol</code>은 tolerance의 약자이며 오차범위를 뜻한다. SGDClassifier는 에포크 반복 동안 성능 개선이 없으면, 즉 현재loss &gt; 최저loss - tol인 경우 학습을 멈추는 경향이 있는데 지멋대로 멈추지 마라고 할 때 <code>tol=None</code>을 해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[논리회로설계및실험 4주차]]></title>
            <link>https://velog.io/@saepal_cse/%EB%85%BC%EB%A6%AC%ED%9A%8C%EB%A1%9C%EC%84%A4%EA%B3%84%EB%B0%8F%EC%8B%A4%ED%97%98-4%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@saepal_cse/%EB%85%BC%EB%A6%AC%ED%9A%8C%EB%A1%9C%EC%84%A4%EA%B3%84%EB%B0%8F%EC%8B%A4%ED%97%98-4%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Fri, 11 Oct 2024 18:54:09 GMT</pubDate>
            <description><![CDATA[<h2 id="1-조합회로와-순차회로의-차이에-대한-이해">1. 조합회로와 순차회로의 차이에 대한 이해</h2>
<p>중요하다. 24년 시험에 이것에 대한 용어 맞추기 문제를 냈었음.</p>
<h3 id="조합회로">조합회로</h3>
<p>조합회로는 입력이 출력을 결정하는 회로이다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/77357967-f1ae-49b1-bf58-0eac922a6e91/image.png" alt=""></p>
<p>버튼 A를 누르고 있는 동안 전구에 불이 들어오게 되는 회로랑 같고 우리가 흔히 아는 and, or gate를 이용한 회로들이 다 조합회로에 속한다.
즉, <strong>입력이 그대로 출력에 반영되는 회로</strong>라고 할 수 있다.</p>
<h3 id="순차회로">순차회로</h3>
<p>순차회로는 현재 입력과 이전 상태의 조합으로 출력이 결정되는 회로이다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/fea81762-ed7a-469b-86dd-8fcb900a4d8a/image.png" alt=""></p>
<p>전구가 꺼진/켜진 상태에서 버튼 A를 누르면 전구가 켜짐/꺼짐 된다는 예를 살펴보자.
이전 상태 + 현재 입력(버튼 누름) + 현재 상태(출력인 셈)인 셈이다.</p>
<p>저 그림을 보면 버튼을 눌렀을 때 신호가 rising된다. 이런 빨간색 부분을 rising edge라고 할것이다. 버튼 a가 rising 되었을 때 전구는 0-&gt;1로 전환이 되고, 그다음은 1-&gt;0으로 전환이 된다.</p>
<p>일단 순차회로라는 녀석이 다분히 복잡한 녀석이구나... 만 알고 그다음으로 넘어가자.</p>
<h2 id="2-flip-flop의-동작과-상태에-대한-이해">2. Flip-flop의 동작과 상태에 대한 이해</h2>
<p><a href="https://homubee.tistory.com/47">flip flop에 대해 더 자세히 알고 싶다면 클릭</a></p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/84c4f06d-aeb8-48ba-a910-e022de8d426b/image.png" alt=""></p>
<h3 id="flip-flop">Flip-flop</h3>
<p>1bit의 정보를 저장할 수 있는 회로이다.</p>
<p>위의 출처 티스토리에서 이해할 수 있듯, flip flop은 clock이란 신호에 따라 작동하는 소자이다. _clock=clk_과 동일</p>
<p>뒤에 나오지만 flip-flop이 여러개 모여서 레지스터가 되면 이제 n bit의 정보 저장이 가능하다.</p>
<p>flip-flop은 대표적인 순차회로이다.
이전 상태를 반영해 현재 상태가 된다는 것은 이전을 <strong>기억</strong>한다는 뜻인데, 특히 d flip-flop은 캡쳐를 해서 이전 상태를 끌고 가므로 <strong>기억</strong>한다고 봐도 무방하다. 캡쳐에 대한 것은 조금 있다가 나온다.</p>
<h4 id="d-flip-flop">d flip flop</h4>
<p>d flip-flop은 data 혹은 delay flip-flop의 약자이다. 다음 말을 잘 이해했다면 부가설명은 안 봐도 좋다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/9f9261ac-65b0-458d-81b4-60cc29add0f4/image.png" alt=""></p>
<blockquote>
<p>d flip flop은 클럭의 rising edge가 발생한 순간의 Din값을 캡쳐하여 다음 클럭의 rising edge가 발생할 때까지 저장함</p>
</blockquote>
<p>저 말에 부가 설명을 하자면, d flip-flop은 플립플롭이기 때문에 클럭 동기식이다. 영어로 하면(Clock) Synchronous D flip-flop. 클럭 동기식은 clock의 edge에서 flip-flop의 Qout이 동일하게 움직인다는 뜻이다.</p>
<p>사진을 보면 클락이 라이징될 때 din의 1을 캡처해서 다음 클락이 rising 될 때까지 끌고간다. 그리고 다음 클락이 rising 되면 din의 0을 캡쳐해서 끌고간다.</p>
<h4 id="회로-그릴-때">회로 그릴 때</h4>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/9343658a-c32f-4bcd-9bb6-6631c72fafc3/image.png" alt=""></p>
<ul>
<li><p>clock은 하나의 input 소자로 다 연결하면 된다.</p>
</li>
<li><p>d는 data 입력값이고 Q는 출력값이다. reset은 다음 사진에서 설명할거지만 하나의 reset으로 연결한다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/0f905553-7c1b-432e-8df8-fe9eb12a356c/image.png" alt=""></p>
</li>
<li><p>quartus에서 symbol 입력하는 빈 창에 dff치면 d flip flop이 나온다.</p>
</li>
<li><p>일반적인 d flip flop을 보면 reset에 not(동그라미)이 붙어있다. 이것을 reset not 줄여서 rstn이라고 한다.
reset이라는 건 0으로 초기화되는 것인데, 일반적인 소자에서는 reset에 not이 붙여져 있으므로 reset이 1일 때 Qout이 0이 된다는 점 조심해야 한다!!</p>
</li>
</ul>
<p>계속 헷갈리는 부분인데 꼭 숙지하도록~</p>
<blockquote>
<p>dff가 있는 회로에서는 rst에 not이 필수적으로 붙어있기 때문에 1일때 reset이 비활성화, rst이 0일때 reset이 활성화이다. 그런데 나중 가서는 보드에서 실습할 때는 reset을 아무데도 안쓰이는 핀에다가 연결시키기 때문에 0일 때 비활성화로 만들어야 한다. 따라서 보드에서 실습할 때는 input인 rst에다가 not 기호를 붙여서 실습해야 한다.</p>
</blockquote>
<h4 id="제어신호를-이용한-값의-저장도-가능">제어신호를 이용한 값의 저장도 가능</h4>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/d9684cff-572e-47a1-983b-6bebfc4cf7b9/image.png" alt=""></p>
<p>앞에 사진에서 ce와 mux가 추가된 그림이다.
제목을 뜻풀이 하자면 제어신호를 이용한다는 게 mux의 입력신호 ce를 활용한다는 뜻이다.</p>
<blockquote>
<p>멀티플렉서(multiplexer) 또는 mux는 여러 아날로그 또는 디지털 입력 신호 중 하나를 선택하여 선택된 입력을 하나의 라인에 전달하는 장치이다 = ce에 따라 둘중 하나 선택</p>
</blockquote>
<p>ce는 clock enable의 약자로 dff에 들어가는 clock을 enable 해줄지 아닐지 고려한다.</p>
<blockquote>
<p>ce가 0이면 현재 상태를 유지한다.
ce가 1이면 D의 값으로 초기화한다.</p>
</blockquote>
<p>왜냐면
ce가 0이면
dff이 아무리 clock rising해도 반응을 안한다
= feedback 신호(이전신호)가 그대로 다음신호로 들어간다</p>
<p>반면, ce가 1이면
이전 상태와 상관없이 clk에 따라 d값이 1이면 Qout이 1이된다.
d값이 0이 되면 Qout이 0이 된다.</p>
<h2 id="3-register의-이해와-구현">3. Register의 이해와 구현</h2>
<p>드디어 register다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/20e3e1ba-cf13-48ac-8a06-4028554945dd/image.png" alt=""></p>
<p>register</p>
<ul>
<li>n개의 flip-flop가 병렬로 이루어짐</li>
<li>각 ff은 동일 clock, 동일 reset으로 연결됨</li>
<li>레지스터로 데이터의 이동을 할 수 있는데 일반적으로는 register의 데이터는 동시에 전달된다.</li>
</ul>
<p>shift register</p>
<ul>
<li>그러나 shift register는 데이터가 <strong>동시</strong>가 아니라 그다음 clock을 만났을 때 전달되는 레지스터이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/3c0b17d8-59fd-4154-80aa-f303f42f4392/image.png" alt="">
<img src="https://velog.velcdn.com/images/saepal_cse/post/1d41cdc4-a538-454c-9029-07bfb267a147/image.png" alt=""></p>
<p>뭐 쭉쭉 오른쪽으로 넘겨지면? 결과값으로 1이 나오게 되는데 이건 생략. 쭉쭉 단계별로 넘어가는 것 = 이건 clock을 만났을 때 = clock이 rising일 때를 의미한다.
<del>ppt에는 input이 계속 1이라고 잘못 기재되어 있었음</del></p>
<h2 id="4-실습">4. 실습</h2>
<h3 id="실습1">실습1</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/92ee3a52-6d8c-40b2-bf1f-2821feee9cc8/image.png" alt=""></p>
<p>실습 1번은 두가지 구현이다.</p>
<ul>
<li><strong>synchronus dff with asynchronous reset</strong>
dff는 clk에 대해 동기인데 reset과 clk은 비동기인 경우이고  a-싱크로너스는 비동기라는 뜻
reset이 켜져도 clk과 아~무 상관없이 qout이 바로 reset된다고 생각하면 됨.</li>
<li><strong>synchronous dff with synchronous reset</strong>
clk에 대해 동기인데 reset이 0이 된다 하더라도? clk이 1이 되어야 reset이 된다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/6ac33bd7-abe7-4609-a09e-16fece82ab96/image.png" alt="">
위 사진은 synchronus dff with asynchronous reset 구현한 것.
일반적으로 연결할 곳 다 연결하면 비동기 리셋 dff이다.
결과를 볼 때 조심해야하는 건 아까 말했듯 reset값이 0이 되어야 q도 0이 되는 점이다. not이 붙어있으니까.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/25eddcf2-3398-4e87-a5e4-fb8e31aa5af9/image.png" alt=""></p>
<p>reset=0이면 clk과 상관없이 qout도 0이 됨(빨강)
reset=1이면 clk이 rising일 때 Din의 값을 캡처해서 다음 clk이 rising일 때까지 끌고감. 근데 reset=1 되어도 clk이 rising 안되면 이전 값 끌고감.</p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/e922b4f1-a186-4c79-9bc9-3d55571f94ca/image.png" alt="">
위사진은 동기 리셋이다.
아까랑 다른 점은 
Din이랑 reset이 and gate로 묶여서 dff의 d로 들어간다는 점이 있다. (나머지는 맞는 자리에 clk, qout 연결)</p>
<p>and gate로 묶이는 것의 의미는 
reset이 0이면= reset이 활성화되면, Din이 어떻든 0이고,
reset이 1이면= reset이 비활성화되면, Din 값대로 Din이 들어가게 하는 것인데,
근데 이것은 다 clock의 영향 아래에 놓여있다는 것이다.</p>
<p>따라서 결과를 보면
<img src="https://velog.velcdn.com/images/saepal_cse/post/5c0c9310-b5d1-4a9e-b7b9-f8d624604f71/image.png" alt=""></p>
<p>reset이 0이어도=활성화되어도 clk이 1이지 않으면 qout은 1이고=Din의 값을 반영하고(파란색),
clk이 비로소 rising이면(빨간색) reset을 반영해 qout이 0이 되는 것을 확인할 수 있다.</p>
<blockquote>
<p>clk, reset, din이 한꺼번에 1이 되는 상황에서는 qout이 0이 되는데, 이것은 delay 때문일 것이라고 추측하고 있다. 이유를 아시는 분은 댓글 달아주세요 ㅠㅠ</p>
</blockquote>
<h3 id="실습2">실습2</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/c0731b9e-5b53-4413-bf2f-dda3108ea773/image.png" alt="">
FDRE: Dff with Sync Reset and Clock Enable(A-sync)
앞의 제어신호를 이용한 dff를 그대로 실험해보는 예시이다.</p>
<p>ce와 clk는 무관하게 연결되어 있어서 a-sync이고,
이것은 ce의 의미를 생각해보면 왜 무관하게 연결되어야 하는지 알 것</p>
<blockquote>
<p>ce가 0이면 현재 상태를 유지한다.
ce가 1이면 D의 값으로 초기화한다.</p>
</blockquote>
<p>2:1 mux는 21mux라고 quartus에 검색하면 나온다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/eb6bc5b9-a473-44e5-b448-8918dd3112ef/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/cacad699-205f-45f2-838b-8a857ad13ba2/image.png" alt=""></p>
<h3 id="실습3">실습3</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/82aad0c6-0edc-4d9f-a7e0-8c0ec9aed745/image.png" alt=""></p>
<p>실습3 == shift register 만들기
shift인 이유는 flip-flop이 <strong>직렬</strong>로 연결되어있고 
이전 결과가 다음의 입력이 되기 때문. (= flip된다고 한다)</p>
<p>clock이 rising edge가 되면 이전게 다음으로 넘어가는 거기 때문에
즉, 딜레이가 있기 때문에 다음과 같이 움직인다...
1번째 : 1 0 0 0
2번째 : 0 1 0 0
3번째 : 0 0 1 0</p>
<p>아래처럼 동시에 가는게 아니다.
틀린예 ↓
1번째 : 1 0 0 0
2번째 : 1 1 0 0
3번째 : 1 1 1 0</p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/fad6fa4c-2f10-45ea-9a8c-47161b022e9b/image.png" alt="">
clk에 맞춰 din이 들어갔고
그다음 1이 q3 -&gt; q2 -&gt; q1 -&gt; q0 순으로 들어가는 모양새.
실수로 reset 비활성화되는 부분을 짧게 잡아서 q0까지는 전달이 안되는 모습을 볼 수 있다.</p>
<h3 id="실습4">실습4</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/16b7b61a-6d9d-4eb2-9503-2da04f23f766/image.png" alt=""></p>
<p>4bit register는 4개의 dff를 병렬로 놓는 것이다
din[3:0]에 들어있는 1010값이 그대로 캡쳐되어서
Q[3:0]으로 <strong>동시</strong>에 값이 나온다.
그다음 0101로 지정하면 0101 값이 그대로 값이 나온다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/cc167f99-affa-4cdb-868c-3bf2b7dac02c/image.png" alt=""></p>
<h3 id="실습5">실습5</h3>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/dd14260c-7321-4a9f-b1c5-1ea61ad7c795/image.png" alt="">
저기 오타가 있는데 A가 첫번째 레지스터의 출력값이자 중간값,
B가 결과값이다. 조심!</p>
<p>실습4의 4비트 레지스터를 직렬로 나두면 된다. =3주차의 심볼화로 하면 더 간단함
d에 1 1 0 0을 넣어서 A값이 <strong>1 1 0 0 *<em>일때
B값은 0 0 0 0 이다.
그다음 clk이 되면
d에 0 0 1 1을 넣었기에 A가 0 0 1 1이 되고
B값은 이전의 d에서 넘어와서 *</em>1 1 0 0</strong>이 된다.
즉 shift 되는 4bit 레지스터 완성.</p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/8e03fa94-a3a3-4006-895e-656731df57de/image.png" alt=""></p>
<p>회로를 보면 두개의 레지스터를 심볼화해서 나타내면 더 간단한 걸 알 수 있다.</p>
<p>그리고 ce에 따라서 shift 되어야 하는데,
기존에는 clk에 맞춰서 shift되었기 때문에
clk과 ce를 and gate로 묶으면 이젠 clk이 있어도 ce가 없으면 작동을 안하게 되므로,
원하던 대로 ce에 맞춰서 shift되게 할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch03.회귀 알고리즘과 모델 규제]]></title>
            <link>https://velog.io/@saepal_cse/ch03.%ED%9A%8C%EA%B7%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B3%BC-%EB%AA%A8%EB%8D%B8-%EA%B7%9C%EC%A0%9C</link>
            <guid>https://velog.io/@saepal_cse/ch03.%ED%9A%8C%EA%B7%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EA%B3%BC-%EB%AA%A8%EB%8D%B8-%EA%B7%9C%EC%A0%9C</guid>
            <pubDate>Tue, 08 Oct 2024 17:15:54 GMT</pubDate>
            <description><![CDATA[<h2 id="03-1-k-최근접-이웃-회귀">03-1 k-최근접 이웃 회귀</h2>
<p>지도 학습 알고리즘 이렇게 두가지로 나뉘어진다.
-분류
-회귀</p>
<h3 id="회귀란">회귀란?</h3>
<p>샘플을 바탕으로 임의의 어떤 숫자를 <strong>예측</strong>하고자 하는 알고리즘
<del>그럼 예측이라고 하면 되지 왜 회귀라고 했을까는 사족</del></p>
<h3 id="k-최근접-이웃-분류와-k-최근접-이웃-회귀의-차이">k-최근접 이웃 분류와 k-최근접 이웃 회귀의 차이</h3>
<ul>
<li>분류
<img src="https://velog.velcdn.com/images/saepal_cse/post/eccb3fca-8fc4-4b5d-a9f8-aa83631e8010/image.png" alt=""></li>
<li>회귀
<img src="https://velog.velcdn.com/images/saepal_cse/post/b49271b4-4faa-4d48-a768-4d76ff65b368/image.ng" alt="회귀"></li>
</ul>
<h3 id="데이터-준비">데이터 준비</h3>
<p>우선 농어의 길이를 특성, 무게를 타깃이라고 하고 훈련을 위해 train_test_split() 함수를 이용한다.</p>
<pre><code>from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight)</code></pre><p>여기서 중요한 점은 사이킷런에서 훈련 세트는 2차원 배열이여야 하는데, 지금 구한 건 1차원 배열이란 것이다. 1차원 배열을 2차원 배열로 바꾸는 방법은 열 하나를 추가하는 것이다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/d1b2484b-d658-4723-b96b-33612adfb58d/image.png" alt="">
이렇게. 파이썬에서 1차원 배열의 크기는 원소가 1개인 튜플로 나타내고 크기는 <code>reshape(3,1)</code>과 같이 바꿀 수 있다. 귀찮으면 <code>reshape(-1,1)</code>도 가능한데 <code>-1</code>은 나머지 원소 갯수로 모두 채우라는 것을 의미한다. </p>
<blockquote>
<p>이는 열의 값은 특정 정수로 지정이 되어있을 때, 남은 배열의 길이와 남은 차원으로부터 추정해서 <strong>알아서 지정</strong>하라는 의미입니다.
<a href="https://yololife-sy.medium.com/python-reshape-1-1-%EC%97%90%EC%84%9C-1%EC%9D%98-%EC%9D%98%EB%AF%B8-97b713be5230">-1의 의미가 이해가 안된다면 여길 클릭</a></p>
</blockquote>
<p>밑의 이미지는 별개의 내용인데 <code>reshape</code>를 하면 어떤 식으로 숫자를 잘라서 구겨 넣는지 궁금해서 해봤다. 열 기준으로 잘 잘라 넣는가보다.
그리고 하면서 깨달았는데 <code>reshape</code>는 <code>sorted</code>처럼 원본에 영향을 안미치는 함수이다. 그래서 변형시킨 걸 원본에 적용시키고 싶으면 <code>arr = arr.reshape(2,2)</code>이렇게 다시 써줘야한다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/8c6593da-d757-4406-b126-f32a2dbd5419/image.png" alt=""></p>
<h3 id="결정계수r2">결정계수(R^2)</h3>
<p>준비한 데이터로 <code>KNeighborsRegressor()</code> 클래스를 활용하여 <code>fit</code>하면 된다.</p>
<p>결정계수 : coefficient of determination
결정계수는 회귀에서의 스코어이다.
분류에서의 스코어는 정답을 맞춘 비율이 되지만 회귀에서의 스코어는 예측한 것이 타깃에 가깝냐 평균에 가깝냐가 된다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/2328d5a5-f811-452c-9ea6-5f4674763e46/image.png" alt="">
즉, 예측이 타깃에 가까우면 분자가 커져 1에 가까워지고, 예측이 평균에 가까우면 분모가 커져 0에 가까워진다.</p>
<p>예측이 평균과 얼마나 차이가 나는지 정확하게 알고 싶다면 다음의 코드를 참고하면 된다.</p>
<h3 id="타깃과-예측의-절댓값-오차의-평균">&#39;타깃과 예측의 절댓값 오차&#39;의 평균</h3>
<pre><code>from sklearn.metrics import mean_absolute_error
test_prediction = knr.predict(test_input)
mae = mean_absolute_error(test_target, test_prediction)
print(mae)</code></pre><p>19g 정도 차이가 남을 확인할 수 있었다.</p>
<h3 id="과대적합-vs-과소적합">과대적합 vs 과소적합</h3>
<p>과대 적합 : 훈련 세트만 과도하게 스코어가 높은 경우
과소 적합 : 둘 다 낮거나 테스트 세트만 스코어가 높은 경우
과대 적합의 경우 원인 예시</p>
<ul>
<li>데이터 세트 내 데이터가 충분하지 못한 경우</li>
<li>데이터 세트 내 분산이 크거나 노이즈가 큰 경우 (이 경우 노이즈까지 학습해버림)
과소 적합의 경우 원인 예시</li>
<li>모델이 너무 단순하여 훈련 세트에 적절히 훈련되지 않는 경우</li>
<li>데이터 세트 내 데이터가 충분하지 못한 경우
지금 예제의 문제는 과소적합이기 때문에 k-최근접 이웃 회귀 알고리즘에서는 <code>k_neighbors</code>의 값을 작게 해주면 국지적으로 판단하여 조금 더 복잡성을 주어 훈련 세트에 맞게 훈련될 수 있다.
<del>반대의 경우에는 이웃의 값을 크게 해주면 된다</del></li>
</ul>
<h2 id="03-2-선형-회귀">03-2 선형 회귀</h2>
<p>k-최근접 이웃 회귀 알고리즘을 쓰면 훈련 세트에 비해 너무 벗어나는 데이터는 이상하게 판단한다...
그야 당연히 주변의 3개쯤의 평균 값을 계산해서 예측하는 것이기 때문이다.</p>
<p>그것의 해결법!!! <strong>선형 회귀</strong>에 대해 소개한다.</p>
<h3 id="선형-회귀">선형 회귀</h3>
<p><code>sklearn.linear_model</code> 패키지에 <code>LinearRegression</code> 클래스를 활용해서 만들 수 있다.</p>
<p>선형회귀 알고리즘을 사용해서 얻어진 직선에는 절편이 있다. 그것은 각각 <code>lr</code> 객체의 <code>coef_</code>와 <code>intercept_</code> 속성에 저장되어 있다.</p>
<blockquote>
<p>coefficient = 계수
intercept = 절편</p>
</blockquote>
<pre><code class="language-python">print(lr.coef_, lr.intercept_)</code></pre>
<p>이런 계수와 절편을 머신러닝 알고리즘이 찾은 값이란 의미로 <code>model parameter</code>라고 부른다. 앞으로의 많은 머신러닝 알고리즘의 훈련과정은 이런 모델 파라미터를 찾아나가는 여정인 것이다. 참고로 k-최근접 이웃 알고리즘에는 그런 것 없다. <del>사례기반학습</del></p>
<h3 id="다항회귀-polynomial-regression">다항회귀 polynomial regression</h3>
<p>선형회귀로는 완전히 맞는 그래프가 아니어서 예측이 어려웠다. 다항회귀로 가보자.</p>
<p><code>np.column_stack((train_input **2, train_input))</code>의 함수로 2차 방정식에 쓰일 훈련세트를 만들고 테스트 세트도 동일하게 만든다.</p>
<p>그리고 훈련 시키면 이차 함수의 a,b,c(절편)들이 모두 나온다.
이를 바탕으로 이차 함수를 그릴려면 matplotlib의 plot함수를 x를 1로 쪼개서 짧을 직선을 연결연결해서 그리면 된다.</p>
<blockquote>
<p>2차 방정식도 선형 회귀인가요?
맞다. 길이`**2도 결국 왕길이라는 변수이다. 그럼 길이와 왕길이가 무게에 대한 선형 회귀를 할 수 있다. </p>
</blockquote>
<pre><code class="language-python">point = np.arange(15, 50)
plt.scatter(train_input, train_target)
plt.plot(point, 1.01*point**2 - 21.6*point + 116.05)
plt.scatter([50],[1574], marker=&#39;^&#39;)
plt.show()</code></pre>
<p>여기서 <code>plot</code> 함수의 메소드는 x값이랑 y값이다.</p>
<h2 id="03-3-특성-공학과-규제">03-3 특성 공학과 규제</h2>
<p><code>PolynomialFeatures</code> 클래스를 이용해 특성이 많은 선형 회귀를 편하게 진행해보자.</p>
<h3 id="다중회귀">다중회귀</h3>
<p>다중회귀 : 여러 개의 특성을 사용한 선형 회귀
특성공학 feature engineering : 기존의 특성을 사용해 새로운 특성을 뽑아내는 작업
제곱한 것, 두개를 곱한 것, 그리고 나머지 특성들... 이런 모든 특성을 활용하면 어떻게 될지 궁금하지 않나?? 해보자!</p>
<h3 id="데이터-준비-1">데이터 준비</h3>
<p>판다스 : 데이터 분석 라이브러리
데이터프레임 : 판다스의 핵심 데이터 구조</p>
<p><code>column_stack</code> 같은 함수로 일일히 쌓기 보다는 있는 csv활용해서 df 만들자.
<img src="https://velog.velcdn.com/images/saepal_cse/post/4793af6c-6c48-41ed-961b-36a7257544df/image.png" alt=""></p>
<p>데이터 준비는 <code>train_test_split</code>으로 마무리한다.</p>
<h3 id="사이킷런의-변환기-transformer">사이킷런의 변환기 transformer</h3>
<p>transformer : 특성을 만들거나 전처리 하는 클래스</p>
<pre><code class="language-python">poly = PolynomialFeatures(include_bias=False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)</code></pre>
<p>이 transform으로 만든 train_poly를 선형회귀에 사용하면 된다.</p>
<h3 id="다중-회귀-모델-훈련하기">다중 회귀 모델 훈련하기</h3>
<p><code>lr.fit(train_poly, train_target)</code>으로 훈련하면 거의 완벽해진다. 특성이 더 많게 하려면 <code>PolynomialFeatures(degree=5)</code>라는 값으로 설정하면 되지만 그럼 초초초초 과대적합이 되어서 안된다.</p>
<h3 id="규제-regularization">규제 regularization</h3>
<p>모델이 너무 과대 적합되지 않게 훼방을 놓는 일.
선형 회귀 모델에서는 <strong>특성의 계수의 크기를 작게</strong> 하는 일이다.
<img src="https://velog.velcdn.com/images/saepal_cse/post/a9103023-4576-4634-9eba-3f35601b03f5/image.png" alt=""></p>
<p>규제 하기 전에 전처리 하자. 특성 간에 천차만별인 규제가 들어가면 안되므로 표준점수화 시키는 것이다.
이번에는 StandardScaler = 변환기 사용할 것.</p>
<pre><code class="language-python">from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)</code></pre>
<h3 id="릿지-회귀와-리쏘-회귀">릿지 회귀와 리쏘 회귀</h3>
<p>릿지 회귀와 리쏘 회귀의 alpha값을 조절하면서 규제를 조절할 수 있다.
alpha값이 크면 규제 강도 업!
alpha값이 작으면 규제 강도 다운...
강도가 업되면 조금더 과소적합될 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch02. 데이터 다루기]]></title>
            <link>https://velog.io/@saepal_cse/ch02.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%8B%A4%EB%A3%A8%EA%B8%B0</link>
            <guid>https://velog.io/@saepal_cse/ch02.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%8B%A4%EB%A3%A8%EA%B8%B0</guid>
            <pubDate>Fri, 04 Oct 2024 12:52:22 GMT</pubDate>
            <description><![CDATA[<h2 id="02-1-데이터-다루기">02-1 데이터 다루기</h2>
<h3 id="지도학습과-비지도-학습">지도학습과 비지도 학습</h3>
<ul>
<li>지도학습 supervised learning
정답을 준다</li>
<li>비지도학습 unsupervised learning
정답을 안준다</li>
<li><del>강화학습</del>
보상을 이용한다 </li>
</ul>
<p>그럼 QUIZ. k-최근접 이웃 알고리즘은?
바로 지도 학습!</p>
<h3 id="훈련-세트와-테스트-세트">훈련 세트와 테스트 세트</h3>
<p>훈련 세트 : 훈련에 이용한 데이터
테스트 세트 : 테스트에 이용한 데이터
샘플 : 하나의 생선 데이터</p>
<p>훈련 세트로만 훈련과 테스트를 하게 된다면 정확도 100%인 문제가 발생한다.
따라서 훈련 세트와 테스트 세트를 별개로 구분짓는게 좋다.</p>
<h3 id="샘플링-편향-sampling-bias">샘플링 편향 sampling bias</h3>
<p>그런데 구분짓는 행위를 뭐라고 할까? 바로 샘플링이다.
샘플링 : 샘플을 뽑는 행위 -&gt; 훈련 세트와 테스트 세트에 적절히 분배하기 위함
샘플링 편향 : 적절히 분배가 안된 상태
샘플링 편향이 나지 않게 뽑으려면 어떻게 하지?</p>
<h3 id="넘파이">넘파이</h3>
<p>파이썬의 <strong>배열</strong> 라이브러리
샘플링 편향이 나지 않게 넘파이 라이브러리를 사용해보자.</p>
<ol>
<li>인덱스 순서를 1,2,3,.. 이 아니라 2, 49, 12, ... 가 되게 섞는다.<pre><code>index = np.arange(49) # 0에서 48까지 1씩 증가하는 인덱스 만들기
np.random.shuffle(index) # 인덱스 섞기</code></pre></li>
<li>넘파이의 <strong>배열 인덱싱</strong> 사용한다.
배열 인덱싱 : 1개의 인덱스가 아닌 여러 개의 인덱스로 한 번에 여러 개의 원소 선택 가능<pre><code>input_arr[1,3] # 예시. 두번째 네번째 샘플 선택</code></pre></li>
<li>배열 인덱싱의 인덱스를 넘파이 배열로 준다.<pre><code>train_input = 똑같은
train_target = 방식
test_input = input_arr[index[35:]] # 여기서 index[35:]는 넘파이 배열
test_target = target_arr[index[35:]]</code></pre></li>
</ol>
<p>이렇게 하면 정확도 100프로 모델이 된다.</p>
<h2 id="02-2-데이터-전처리">02-2 데이터 전처리</h2>
<h3 id="넘파이로-데이터-준비하기">넘파이로 데이터 준비하기</h3>
<p>이제 넘파이를 배웠으니 샘플을 만들 때 아래와 같이 만들지 않는다.</p>
<pre><code>[[l,r] for l,r in zip(fish_length, fish_weight)</code></pre><p>바로 np.column_stack( 안에는 튜플 )로 만든다.
튜플이란? 수정할 수 없는 리스트</p>
<pre><code>fish_data = np.column_stack((fish,length, fish_weight))</code></pre><p>또한, 넘파이를 배운 여러분은 타깃 데이터도 더 쉽게 만들 수 있다.</p>
<pre><code>fish_target = np.concatenate((np.ones(35),np.zeros(14)) # 사슬로 잇다</code></pre><h3 id="사이킷런으로-훈련-세트와-테스트-세트-나누기">사이킷런으로 훈련 세트와 테스트 세트 나누기</h3>
<p>그리고 마지막으로, 넘파이를 배웠기 때문에! 여러분은 훈련 세트와 테스트 세트를 나눌 때 인덱스 셔플 할 필요가 없다.</p>
<pre><code>from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split( fish_data, fish_target )</code></pre><p>이 함수는 기본적으로 25퍼센트를 테스트 세트로 떼어 낸다.
그런데 무작위로 데이터를 나눴을 때 샘플링 편향이 일어날 수 있다. 다시 말해 훈련 세트에서의 도미와 빙어 비율보다 테스트 세트에서의 도미와 빙어 비율이 더 높거나 낮을 수 있다는 뜻이다. 이것은 특히 훈련 데이터가 적거나, 특정 클래스의 샘플 개수가 적을 때 특히 그렇다.
해결법 : stratify = fish_target 매개변수 추가! 그렇게 하면 비율 똑같이 들어간다.</p>
<pre><code>train_input, test_input, train_target, test_target = train_test_split( fish_data, fish_target, stratify=fish_target )</code></pre><h3 id="수상한-도미-한-마리">수상한 도미 한 마리</h3>
<p>이렇게 하고 도미인 데이터 하나 predict 해보자. 어라? 도미가 아니라 빙어라고 주장하네.
이웃들을 다른 점으로 표현해 봅시다.</p>
<pre><code>distances, indexes = kn.kneighbors([[25,150]])
plt.scatter(train_input[indexes, 0], train_input[indexes,1], marker=&#39;D&#39;) ????</code></pre><p>이상하네. 표현해보면 빙어가 이웃 중에 4개입니다. 근데 점 자체는 도미랑 더 가까워 보여요.
무슨 일일까요?</p>
<h3 id="기준을-맞춰라">기준을 맞춰라</h3>
<p>x,y의 거리 비율이 안 맞아요. == 두 특성의 <strong>스케일</strong>이 다르다.
해결법-1.</p>
<pre><code>plt.xlim((0,1000)) # x 범위를 y 범위와 동일하게 조정해준다.</code></pre><p>로 해볼까요? 그럼 너무 일직선 처럼 보여요 ㅠㅠ.</p>
<p>해결법-2. 표준점수
표준점수는 값에서 평균을 빼고 표준편차를 나누어 주면 된다.</p>
<pre><code>mean = np.mean(train_input, axis=0)
std = np.std(train_input, axis=0)
train_scaled = (train_input -mean)/std</code></pre><p>브로드캐스팅 : 모든 행에 있는 데이터를 표준점수 계산해주는 기능</p>
<pre><code>test_scaled = (test_input -mean)/std
</code></pre><h3 id="전처리-데이터로-모델-훈련하기">전처리 데이터로 모델 훈련하기</h3>
<p>맞추고 싶은 데이터도 표준점수로 만들고, 훈련 세트, 테스트 세트도 표준점수로 만들어서 fit해주면 완성이다.</p>
<p>완성!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[firebase] 학교 이메일로 인증 메일이 안올 때]]></title>
            <link>https://velog.io/@saepal_cse/firebase-%ED%95%99%EA%B5%90-%EC%9D%B4%EB%A9%94%EC%9D%BC%EB%A1%9C-%EC%9D%B8%EC%A6%9D-%EB%A9%94%EC%9D%BC%EC%9D%B4-%EC%95%88%EC%98%AC-%EB%95%8C</link>
            <guid>https://velog.io/@saepal_cse/firebase-%ED%95%99%EA%B5%90-%EC%9D%B4%EB%A9%94%EC%9D%BC%EB%A1%9C-%EC%9D%B8%EC%A6%9D-%EB%A9%94%EC%9D%BC%EC%9D%B4-%EC%95%88%EC%98%AC-%EB%95%8C</guid>
            <pubDate>Tue, 20 Aug 2024 02:01:46 GMT</pubDate>
            <description><![CDATA[<p>gmail.com으로 보내니 잘 됨. 코드에는 문제가 없는 모양이다.</p>
<p>결국 학교 이메일 시스템에서 자체적으로 막고 있는 것으로 판단하고 학교 이메일 담당 부서에 전화를 했다.</p>
<p>담당자 분이 우리 firebase 이메일 주소인 (발신자) <a href="mailto:seguenDB@firebaseapp.com">seguenDB@firebaseapp.com</a>과 받는 메일인 <a href="mailto:na@pusan.ac.kr">na@pusan.ac.kr</a> (수신자)를 물어보셨다.</p>
<p>그리고 firebaseapp.com을 화이트리스트 처리 했으니 다시 보내보라고 하셨다.</p>
<p>결과적으로 인증 메일이 왔다! 합삐~!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드 스튜디오 project 탭에 android가 안보일 때]]></title>
            <link>https://velog.io/@saepal_cse/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-project-%ED%83%AD%EC%97%90-android%EA%B0%80-%EC%95%88%EB%B3%B4%EC%9D%BC-%EB%95%8C</link>
            <guid>https://velog.io/@saepal_cse/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-project-%ED%83%AD%EC%97%90-android%EA%B0%80-%EC%95%88%EB%B3%B4%EC%9D%BC-%EB%95%8C</guid>
            <pubDate>Wed, 17 Jul 2024 15:53:25 GMT</pubDate>
            <description><![CDATA[<p>참고
<a href="https://github.com/firebase/FirebaseUI-Android/issues/1349">https://github.com/firebase/FirebaseUI-Android/issues/1349</a></p>
<p>문제상황 : 
안드로이드 스튜디오로 협업을 하는데 pull을 받아왔을 때 project 탭에서 안드로이드 옵션이 안보인다. (윈도우 기준)
<img src="https://velog.velcdn.com/images/saepal_cse/post/27a4a15f-5e04-403a-ae78-da4c67697a76/image.png" alt="">
이렇게 android 항목이 사라진 것을 알 수 있다. 원래 android 항목으로 개발하는 것이 보편적이기 때문에 꽤나 곤란한 상황이다.</p>
<p>해결방법 :
0. 기다린다.....
안드로이드 스튜디오에서 파일을 막 가져온 상황이라면 더 그렇다.
진행과정이 우측 하단에 표시되는데 처음에는 표시되는지도 모르고 왜 안나오지 했다. 그러나 모든 과정이 끝났다면 보이는 경우가 999999퍼센트였다.</p>
<p>그래도 안되면</p>
<ol>
<li><p>모든 .idea 폴더를 지운다.  </p>
</li>
<li><p>file - new project에서 import project - 프로젝트 안에 있는 gradle을 누른다. <em>&quot;Open an existing Android Studio project&quot;는 안됨</em></p>
</li>
<li><p>Import project from external model 옵션을 누른다. create한다.</p>
</li>
</ol>
<p>원인 : gradle에서 import를 제대로 해주지 않는 까닭이다. 그래서 import를 해주면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ch01. 나의 첫 머신러닝]]></title>
            <link>https://velog.io/@saepal_cse/%EC%A0%95%EB%A6%AC-%ED%98%BC%EA%B3%B5%EB%A8%B8%EC%8B%A0-chapter-1</link>
            <guid>https://velog.io/@saepal_cse/%EC%A0%95%EB%A6%AC-%ED%98%BC%EA%B3%B5%EB%A8%B8%EC%8B%A0-chapter-1</guid>
            <pubDate>Sun, 14 Jul 2024 09:31:09 GMT</pubDate>
            <description><![CDATA[<h2 id="01-1-인공지능-머신러닝-딥러닝">01-1 인공지능, 머신러닝, 딥러닝</h2>
<h3 id="ai-ai하는데-그게-뭐야">AI, AI하는데 그게 뭐야?</h3>
<p>AI는 두 번의 붐이 있어 왔고 2016년 알파고의 등장으로 지금 점점 주가가 올라가는 몸이다.</p>
<p>AI는 artificial intelligence로 사람 같이 생각하는 지능을 가진 프로그램이다.</p>
<p>인공일반지능 artificial general intelligence는 strong AI라고도 불리며 사람과 거의 유사한 지능을 가진 인공지능을 말한다.</p>
<p>그와 반대로 약인공지능 weak AI는 우리 주변에서 볼 수 있는 노래추천, 자율주행기능, 기계번역과 같이 우리의 보조 비서 역할을 해주는 인공지능이라고 생각하면 된다.</p>
<h3 id="머신러닝이란">머신러닝이란?</h3>
<p>AI의 하위분야로 일일이 프로그래밍을 하지 않아도 데이터 속에서 규칙을 찾아 학습하는 알고리즘을 연구하는 분야이다.</p>
<p>머신러닝은 _사이킷-런_이라는 파이썬의 라이브러리를 통해 사용할 수 있다. 이 오픈소스 라이브러리는 유수의 석학들이 연구한 알고리즘 중 쓸만한 것들을 모아 사용하기 쉽게 모아둔 라이브러리이다.</p>
<p>사이킷-런의 의미는 이 라이브러리가 나오고부터 누구나 파이썬만 조금 안다면 머신러닝을 시작할 수 있게 만들었다는 데서 온다.</p>
<p>그렇기에 우리는 새로운 이론이나 기술을 &quot;코드로 구현&quot;하지 못하면 그것을 가치가 없다고 평가하게 되었다.</p>
<h3 id="딥러닝이란">딥러닝이란?</h3>
<p>머신러닝 알고리즘들 중에 인공 신경망 Artificial neural network을 활용한 방법들의 통칭이다. 딥러닝이 곧 인공 신경망이라고 보면 된다.</p>
<p>인공 신경망이 뭔지는 모르겠지만 이미지 처리 기술에 합성곱 신경망을 사용하는 게 대세이다.</p>
<p>앞에서 머신러닝 라이브러리 사이킷-런을 소개했듯 딥러닝에서도 양대산맥 라이브러리가 존재한다.</p>
<p>바로 구글의 tensorflow, 페이스북의 pytorch이다.</p>
<h2 id="01-2-주피터-노트북">01-2 주피터 노트북</h2>
<p>우리는 <strong>구글 코랩</strong>을 이용해 실습을 한다. 이것은 클라우드 기반이라 컴퓨터 성능과는 무관하다.</p>
<p>코랩은 클라우드 기반의 <strong>주피터 노트북</strong> 개발 환경이다.</p>
<p>주피터 노트북이란?</p>
<p><strong>주피터 프로젝트의 대표 제품</strong>으로 이 프로젝트는 구글이 <strong>대화식 프로그래밍 환경인 주피터</strong>를 만드는 프로젝트이다. 이 프로젝트는 파이썬부터 시작해서 최근에는 다른 언어까지 지원하게 되었다.</p>
<p>말이 좀 와닿지는 않지만 아무튼 파이썬 실행 사이트(?) 정도로 나는 이해했다.</p>
<p>코랩 : 웹 브라우저 기반의 파이썬 코드 실행 환경
노트북 : 코랩의 프로그램 작성 단위이며 대화식이라 데이터 분석에 편함</p>
<h2 id="01-3-마켓과-머신러닝">01-3 마켓과 머신러닝</h2>
<p>생선이 도미이냐 빙어이냐 구분하는 머신러닝 모델을 만들어보자.</p>
<p>&lt;용어 설명&gt;</p>
<p>생선의 종류할 때 종류는 머신러닝에서 <code>class</code>라고 부르고 분류하는 것은 <code>classfication</code>라고 한다. 특히 이번 예제처럼 2개 중 하나의 것을 고르는 분류는 이진 분류 <code>binary classfication</code>이라고 한다.</p>
<p>특성은 <code>featrue</code>이라고 하며 생선의 길이, 무게 같은 데이터의 특징이라고 생각하면 된다.</p>
<p>용어 정리는 이쯤하고 차차 부족한 건 추가하겠다.</p>
<h3 id="k-nearest-neighbors-k-최근접-이웃-알고리즘">K-Nearest Neighbors (K-최근접 이웃 알고리즘)</h3>
<p>이번 머신러닝 모델을 만들 때 필요한 알고리즘.
알고리즘이라고 할 것도 없는게 모델이 <code>from sklearn.neighbors import KNeighborsClassifier</code>에서 <code>KNeighborsClassifier()</code>이라고 치면,</p>
<p>모델의 fit() 메소드 안에 값 데이터랑 정답 데이터만 넣으면 주변 5개의 이웃을 보고 더 많은 쪽의 (도미, 빙어) 종류를 정답으로 내어놓는 알고리즘이다. 단순 연산인 셈.</p>
<p>그리고 이웃 갯수는 5개가 default이며 <code>k_neighbors = 49</code>와 같이 변경도 가능. 이 경우 잘못하면 정확도가 훅 떨어진다. 이유는 후술.</p>
<blockquote>
<p>참고.
이 알고리즘을 사용할 때는 scatter plot를 활용하여 시각적으로 확인하는 작업을 많이 한다. 그 코드는 머리 속에 익히자.</p>
</blockquote>
<pre><code class="language-python">import matplotlib.pyplot as plt
plt.scatter(x,y)
plt.xlabel = xname
plt.ylabel = yname
plt.show()</code></pre>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/c8963621-a6a4-4c04-9828-fea8dbdc8600/image.png" alt=""></p>
<h3 id="kneighborsclassifier-모델의-메소드">KNeighborsClassifier() 모델의 메소드</h3>
<ul>
<li><p><code>kn.fit(fish_data, fish_target)</code> 이때 fish_data는 이중 리스트이며 [길이,무게] 이렇게 이루어진 데이터묶음이 나열되어있다.
값 데이터와 정답 데이터를 통해 <code>train</code> 시킬 수 있다.</p>
</li>
<li><p><code>kn.score(fish_data, fish_target)</code>
정확도 accuracy를 0에서 1사이 값으로 확인 가능하다.</p>
</li>
<li><p><code>kn.predict([[30,600]])</code> 
30에 600을 가진 생선이 도미이냐를 물어보기 가능하다. array([1])의 값으로 도미임을 알려주는데 일단 1이냐만 보고 array는 무시하자.</p>
</li>
<li><p><code>kn._fit_X</code> 
kn의 fish_data를 확인 가능</p>
</li>
<li><p><code>kn._Y</code> 
kn의 fish_target을 확인 가능</p>
</li>
<li><p><code>kn49 = KNeighborsClassifier(n_neighbors=49)</code>
이웃의 수를 49로 변경하면 모든 답은 도미로 나온다. 그 이유는 원래 fish_data의 값에 35개가 도미이고 14개가 빙어라서 다수결의 법칙에 따라 늘 도미만 나오게 되는 것이 까닭이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0x0B강 재귀를 듣고 배운 점]]></title>
            <link>https://velog.io/@saepal_cse/0x0B%EA%B0%95-%EC%9E%AC%EA%B7%80%EB%A5%BC-%EB%93%A3%EA%B3%A0-%EB%B0%B0%EC%9A%B4-%EC%A0%90</link>
            <guid>https://velog.io/@saepal_cse/0x0B%EA%B0%95-%EC%9E%AC%EA%B7%80%EB%A5%BC-%EB%93%A3%EA%B3%A0-%EB%B0%B0%EC%9A%B4-%EC%A0%90</guid>
            <pubDate>Wed, 10 Jul 2024 09:15:09 GMT</pubDate>
            <description><![CDATA[<h3 id="귀납적-사고">귀납적 사고</h3>
<p>하노이탑 문제를 알고 있었는데 이것이 귀납이라는 것은 생각하지 못했다. 덕분에 재귀는 귀납으로 풀어야 한다는 행동지침을 명확하게 세울 수 있었다. 특히 2k, 2k+1 과 같은 귀납을 다시 떠올릴 수 있었다는 점에서 큰 수확</p>
<h3 id="베이스-컨디션">베이스 컨디션</h3>
<p>베이스 컨디션의 존재는 알고 있었다.
그러나 문제들을 풀어보면서 그것이 n==1일때 뿐만 아니라 n==k일때로 설정하여 최대치를 설정하는 것도 베이스 컨디션이 될 수 있다는 것을 알게 되었고, 꼭 n이 몇이다 라는 것이 아니더라도 1780번 종이의 개수 같은 문제는 &quot;칸 안의 숫자가 다르면&quot;이 base condition이 되었다. 문제를 많이 풀어보며 주의해야겠다.</p>
<h3 id="함수형-코딩">함수형 코딩</h3>
<p>생각보다 정답코드에 함수형 코딩이 강했다. 이것이 남들이 봤을 때 더 알아보기 쉽고 나도 짤 때 구조화하기 편하므로 더 체화시켜야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[0x08강에서 배운 점]]></title>
            <link>https://velog.io/@saepal_cse/0x08%EA%B0%95%EC%97%90%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EC%A0%90</link>
            <guid>https://velog.io/@saepal_cse/0x08%EA%B0%95%EC%97%90%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EC%A0%90</guid>
            <pubDate>Fri, 28 Jun 2024 07:52:01 GMT</pubDate>
            <description><![CDATA[<p>바킹독님의 실전 알고리즘 강의 0x08를 들으며 배운 점을 정리해보겠다.</p>
<p><img src="https://velog.velcdn.com/images/saepal_cse/post/c3ed5339-9bd9-4ab6-aed7-a0a2dbd299ee/image.png" alt=""></p>
<h3 id="스택-괄호쌍-문제-유형화-가능해짐">스택 괄호쌍 문제 유형화 가능해짐</h3>
<p>코코넛 문제에서부터 골머리를 앓았던 괄호쌍 유형, 드디어 해법을 정리했다. 체화시켜야 한다!</p>
<p>특히 boj4949번: 균형잡힌 세상 문제 - 정답 코드에서 배운 점은 getline(cin, s); 익숙하게 하자는 것이다.</p>
<p>그리고 getline과 종료조건을 어떻게 하면 간단하게 표현할까 고민했는데 정답 코드에서 wow!포인트가 나옴</p>
<pre><code>while(1){
    string s;
    getline(cin,s);
    if(s==&quot;.&quot;) break;
    ...
}
</code></pre><h3 id="stack-생성을-제멋대로-만들지-말자">stack 생성을 제멋대로 만들지 말자.</h3>
<p>  이번 같은 경우에 while문 안에서 새롭게 만들었어야 했는데 괜히 밖에 만들어서 stack이 비워지지 않아 에러를 일으킴. 만들 때도 위치를 조심하자.</p>
<h3 id="top함수-주의점">top함수 주의점</h3>
<p>stack의 top 함수의 경우 꼭 empty 함수와 같이 연결시켜서 생각하는 사고의 흐름 기르자. 에러 나기 딱 좋음.</p>
<h3 id="getline과-cin의-혼용시-주의점">getline과 cin의 혼용시 주의점</h3>
<p>boj3986-좋은단어에서 배운 점인데, cin 뒤에 getline을 혼용하게 되면 getline에 개행문자 (&#39;\n&#39;)이 들어가게 된다. </p>
<p>  이유로는 챗지피티 설명을 인용하겠다.</p>
<blockquote>
<p>  cin으로 입력을 받은 후 getline을 사용하면, getline 함수가 버퍼에 남아 있는 개행 문자를 만나게 됩니다. 이 경우 getline은 빈 줄을 읽게 되어 빈 문자열을 반환하게 됩니다.</p>
</blockquote>
<p>  Q. 그럼 cin, cin을 두 번 쓸 때는 그런 문제가 생기지 않나요?
  A. 왜냐하면 cin은 입력 버퍼에 남아 있는 공백 문자를 무시하고 다음 유효한 입력을 기다리기 때문입니다.</p>
]]></description>
        </item>
    </channel>
</rss>