<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>im_school</title>
        <link>https://velog.io/</link>
        <description>ai school 기간 동안의 TIL!</description>
        <lastBuildDate>Tue, 30 May 2023 17:02:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. im_school. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/im_ngooh" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[논문 리뷰] batch normalization
]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-batch-normalization</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-batch-normalization</guid>
            <pubDate>Tue, 30 May 2023 17:02:11 GMT</pubDate>
            <description><![CDATA[<ul>
<li>본 논문은 Batch Normalization에 대해 처음 다룬 논문으로, Internal Covariate Shift를 해결하고자 Batch Normalization을 도입하였다.</li>
<li>비록 후속 연구에 의해 Batch Normalization 이 Internal Covariate Shift 문제를 해결하지 못한다는 점과 BN의 효과가 smoothing에 의한 것이라는 점이 밝혀졌으나, 그럼에도 불구하고 본 논문에서 제시한 Batch Normalization은 학습 성능 향상 및 시간 단축에 크게 기여하였다.</li>
</ul>
<h2 id="0-abstract">0. Abstract</h2>
<ul>
<li>Deep Neural Network을 학습 시킬 때, 각각의 layer의 parameter값이 바뀜에 따라서, 각 layer에 들어오는 input의 분포가 바뀌게 된다. 이는 learning rate를 더 작은 값을 써야하도록 만들고, parameter initialization을 더욱 주의 깊게 하도록 만들어 학습을 더욱 느려지게 한다.</li>
<li>이러한 현상을 Internal Covariate Shift라고 하며, 본 논문에서는 각 layer의 input을 normalize 함으로써 이 현상을 해결하고자 하였다.</li>
<li>더 자세히는, 각 training mini batch에 대해 normalization을 수행하여 higher learning rate를 사용할 수 있게 하고, less careful initialization 할 수 있게 함으로써 학습 속도의 향상에 기여하였다. 또한 이는 Dropout과 같은 regularization 의 역할도 수행하여 학습 성능 항상에도 기여한다.</li>
</ul>
<h2 id="1-introduction">1. Introduction</h2>
<ul>
<li>SGD나 momentum, Adagrad와 같은 optimization 기법들이 딥러닝의 좋은 성능을 이끌어가고 있다.</li>
<li>SGD가 간단하고 효과적인 방법이긴 하지만, 이는 learning rate, initial values for model paramters와 같은 hyperparameter의 주의깊은 tuning을 요구한다.</li>
<li>또한 각 layer의 input이 앞선 layer의 parameter의 영향을 받는다는 사실은 학습을 더욱 복잡하게 만들고, network parameter의 작은 변화가 network가 깊어짐에 따라 큰 영향을 가져올 수 있다.</li>
<li>이렇게 각 layer의 input의 분포가 계속 변화한다면, 새로운 분포에 계속해서 맞춰 학습해 나가야 하기 때문에 문제가 발생할 수 있다.</li>
<li>learning system의 input distribution이 계속 변화할 때, covariate shift를 겪는다고 말하는데, 이러한 covariate shift는 system 전체로, 그러니까 모든 layer에 대해 확장될 수 있다. 이것이 바로 internal covariate shift이다.</li>
<li>covariate shift가 없을때를 생각해보자. 예를 들어 한 레이어의 output을 input으로 받아 학습하는 layer가 있다면, input distribution의 학습 용이성(train과 test의 분포가 비슷함)은 training을 더욱 efficient하게 만들 것이고, 이는 각 layer에도 적용될 것이다. 레이어가 input의 분포에 다시 적응할 필요성을 없게 만들기 때문이다.</li>
<li>sub network에 대해 input의 분포가 고정된다면, sub network 바깥에 있는 layer에 대해서도 긍정적인 영향이 잇따른다. 예를 들어 sigmoid function을 생각해보자. sigmoid function에 대해 input이 커지면 gradient가 0으로 수렴하여 gradient vanishing 현상이 일어나게 되는데, 이는 모델의 학습 속도를 느려지게 한다. 이때, input x가 그 전 모든 layer들의 parameter의 영향을 받기 때문에, 이 parameter들을 학습 과정 중 변화시킨다면 x를 sigmoid에서 saturated regime of the nonlinearity(기울기가 0에 가까운 부분)로 이동시키고, 수렴을 느리게 만들 것이다.</li>
<li>이러한 문제는 network depth가 깊어짐에 따라 더욱 증폭된다. 이러한 saturation 문제와 vanishing gradient는 RELU함수, 혹은 careful initialzation and small learning rate를 사용하여 해결되고 있다. 그러나, 우리가 nonlinearity input의 분포를 training 과정 도중 안정적이게 만들 수 있다면, 즉 internal covariate shift를 없앨 수 있다면, optimizer는 saturated regime에 도달할 확률이 줄어들고, 학습이 더욱 빨라질 것이다.</li>
<li>deep network 내부에서의 학습 도중 분포의 변화를 internal covariate shift라고 부를 것이며, 본 논문에서는 이를 제거하여 빠른 학습을 진행하고자 Batch Normalization 이라는 기법을 제시한다. 이는 layer input의 평균과 분산을 고정하여 normalization 함으로써 학습의 속도를 빠르게 할 뿐만 아니라, gradient의 parameter의 scale과 초기값에 대한 의존성을 줄이는 효과도 가져올 수 있다. 이를 통해 발산의 우려 없이 higer learning rate를 사용할 수 있다.</li>
<li>ImageNet classification network에 batch normalization을 사용한 결과, 단지 7%의 학습 과정을 통해서 동일한 성능에 도달하였으며, 최종적으로는 학습 성능 향상의 효과까지 있었다. Batch Normalization을 통해 학습한 network들의 ensemble을 통해서는 ImageNet Classification에 대해 최고의 성능을 내었다.</li>
</ul>
<h2 id="2-toward-reducing-internal-covariate-shift">2. Toward Reducing Internal Covariate Shift</h2>
<ul>
<li>Internal Covariate Shift는 학습 과정 중 parameter의 변화로 인한 network activation의 분포 변화를 의미한다.</li>
<li>본 논문에서는 학습 속도를 향상시키기 위해 internal Covariate shift를 줄일 방법을 고안하는 것을 목표로 하였고, layer input의 distribution을 고정시켜 이를 해결하고자 하였다.</li>
<li>논문의 저자들은 처음에 평균을 0으로, 분산을 1로 만들고 decorrelate 시키는 whitening을 시도하였다.</li>
<li>그러나 모든 training step에 대해 whitening을 진행하기 위해서는, network를 직접적으로 수정하거나 parameter를 바꾸어야 했다.</li>
<li>이러한 whitening을 사용했을 때에는 gradient descent 방법의 효과가 감소하는 문제가 있었다. 예를 들어 training data의 activation의 평균을 구하고, 이를 빼는 방식으로 normalize 시킨다면, 학습 과정에서 파라미터의 업데이트와 normalization의 변화가 둘 다 일어나 loss에는 아무런 변화가 생기지 않게 된다. 그렇다면 loss가 줄어들지 않으므로 parameter는 무한히 커지게 되는 문제가 생겼다.</li>
<li>또한, 이러한 whitening을 사용할 때에는 given training example뿐 아니라, 다른 layer에 의해 생성된 example까지 고려해야 하기에, backpropagation을 위해 Jacobian을 계산해야한다.</li>
<li>게다가 Whitening을 진행하기 위해서는 covariance matrix와 그것의 inverse square root를 계산하는 과정이 꼭 필요하기 때문에 상당한 계산량이 필요하다.</li>
<li>따라서 이러한 문제들은 우리로 하여금 미분 가능하면서도 파라미터가 업데이트 될 때마다 전체 training set에 대해 다시 분석할 필요가 없도록 하는 대안을 추구할 필요성을 불러일으킨다.</li>
</ul>
<h2 id="3-normalization-via-mini-batch-statistics">3. Normalization via Mini-Batch Statistics</h2>
<ul>
<li>각각의 layer의 input을 whitening하는 것은 많은 연산을 필요로 하며, 심지어 전 구간에서 미분가능하지도 않다. 따라서 새로운 방법이 필요하였다.</li>
<li>따라서 고안한 새로운 방법은 먼저 각각의 scalar feature들을 평균을 0, 분산을 1로 만들도록 normalize하는 것이다. whitening과는 feature들 간 decorrelation 여부에 차이가 있다.</li>
<li>즉, layer의 각각의 input x에 대해,</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b79b65ec-8b8d-4990-a5d6-08124c25f260/Untitled.png" alt="Untitled"></p>
<p>다음과 같은 방법으로 input을 normalize 시킨다.</p>
<ul>
<li>이때 평균과 분산은 전체 training dataset에 대해 계산한다. 이러한 normalization은 decorrelation 없이도, parameter가 수렴하는 속도를 빠르게 하는 효과가 있다.</li>
<li>그런데, 각각의 layer의 input을 단순히 normalize하는 것은 layer가 표현할 수 있는 정도를 바꾸어버리는 문제가 있다. 예를 들어, sigmoid로 들어가는 input을 normalize한다면, 대부분의 input이 sigmoid 함수의 linear한 부분에 해당하고, nonlinear한 부분으로 가는 것을 제한하여 layer의 nonlinearity를 없앨 수 있다. 따라서 이를 해결하기 위해 γ(k), β(k)를 도입하여 normalized된 값을 스케일링하고 shift하도록 한다. 즉, normalize된 y는 다음과 같아진다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c0d659a5-eda5-47c8-96d2-45a56e097863/Untitled.png" alt="Untitled"></p>
<ul>
<li>이러한 parameter γ, β는 original model parameter들과 함께 학습되는 값이다.</li>
<li>또한, mini-batch를 사용하는 stochastic gradient training 에서는 normalization에 전체 training data에서 얻은 평균과 분산을 사용할 필요가 없다. 이는 mini batch에서 normalization을 진행할때 공분산이 아니라 각 feature에 대한 분산을 계산하기 때문이다. 이렇게 각 mini batch에 대한 평균과 분산을 계산하여 normalization에 사용함으로써, 이러한 통계량들은 gradient backpropagation에 완벽하게 관여할 수 있다.</li>
<li>다음은 학습 과정에서 batch normalization의 알고리즘을 나타낸 것이다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/78bf6f30-2517-43ee-988d-54f032e2cae8/Untitled.png" alt="Untitled"></p>
<ul>
<li><p>파라미터 감마와 베타는 학습되어야 하는 값이다.</p>
</li>
<li><p>입실론은 수치적 안정성을 위해 mini batch 분산에 더해지는 값이다.</p>
</li>
<li><p>먼저 각 미니 배치에 대한 입력값의 평균과 분산을 구하고</p>
</li>
<li><p>이 평균과 분산 값을 사용하여 입력값을 normalize 시킨다.</p>
</li>
<li><p>마지막으로 감마와 베타 값을 사용해 scale과 shift를 진행한다.</p>
</li>
<li><p>이렇게 normalized된 값들은 sub-network, 즉 다른 layer의 input으로 들어가게 되고, 이 값들은 고정된 평균과 분산, 즉 고정된 분포를 가질 것이다.</p>
</li>
<li><p>이렇게 normalized된 input을 사용하여, 각각의 layer에서의 학습이 빨라질 것이고, 결과적으로 전체 네트워크에서의 학습이 빨라질 것이라고 기대할 수 있다.</p>
</li>
<li><p>또한 batch normalization 된 값들은 미분 역시 가능하여, gradient를 계산하고 backpropagation을 진행하는데에도 문제가 없다.</p>
</li>
<li><p>다음은 normalization된 input에 chain rule을 적용한 수식이다.</p>
</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/083daf34-0d79-4196-a6c9-8d212018a2c0/Untitled.png" alt="Untitled"></p>
<ul>
<li>따라서 batch normalization은 미분 가능한 normalization을 제공하여, 모델이 학습할 때 겪는 internal covariate shift 문제를 줄여 학습을 빠르게 한다.</li>
</ul>
<h3 id="31-training-and-inference-with-batch-normalized-networks">3.1 Training and Inference with Batch-Normalized Networks</h3>
<ul>
<li>Batch Normalization을 통해 학습을 진행할때에는 위에서 언급한 알고리즘대로 각각의 mini batch에 대한 평균과 분산을 구해 normalization을 진행하면 되지만, inference 과정에서는 어떤 input이 들어올지 모르므로 batch에 대한 평균과 분산을 구할 수 없다.</li>
<li>따라서, training이 완료된 후 inference과정에서는, normalization에 사용하는 평균과 분산을 batch에 대해 달라지는 값이 아니라, 학습을 진행하는 동안 계산하여 고정된 값으로 사용한다.</li>
<li>평균의 경우 각 mini batch의 표본평균의 평균, 분산의 경우 각 mini batch의 표본 분산의 평균을 사용하고, 이때 이동평균이나 지수평균을 사용한다.</li>
<li>다음은 batch normalization에서 training과 inference가 일어나는 동안의 알고리즘을 나타낸 것이다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/adf10bdc-b8ff-44dc-bbe3-aa3aa1026e1a/Untitled.png" alt="Untitled"></p>
<ul>
<li>앞선 알고리즘과 거의 유사하지만, inference과정에서 normalization에 사용하는 평균과 분산을 고정시킨다는 차이점이 존재한다.</li>
</ul>
<h3 id="32-batch-normalized-convolutional-networks">3.2 Batch Normalized Convolutional Networks</h3>
<ul>
<li>batch normalization은 주로 activation function 전에서 적용되는데, 이는 fully connected layer와 convolutional layer에서 모두 사용될 수 있다.</li>
<li>Convolutional layer에 대해 normalize 하려고 할 때, 동일한 feature map의 요소들은 모두 같은 방법으로 normalized 되어야 한다.</li>
<li>따라서 feature map 별로 감마와 베타를 학습하고, normalization 시키는 방식으로 batch normalization을 수행할 수 있다.</li>
</ul>
<h3 id="33-batch-normalization-enables-higher-learning-rates">3.3 Batch Normalization enables higher learning rates</h3>
<ul>
<li>normalization을 사용하지 않은 deep network에서, 너무 높은 learning rate를 사용하면 gradient가 vanish 혹은 explode되거나, local minima에서 멈추는 문제가 발생할 수 있었다.</li>
<li>Batch Normalization은 네트워크 전반에 걸쳐 activation을 normalization 함으로써, parameter의 작은 변화가 activation들의 변화로 인해 gradient의 큰 변화로 이어지는 것을 막아줌으로써 이러한 문제를 해결할 수 있다.</li>
<li>또한, Batch Normalization은 학습이 parameter의 scale에 무관하게 진행되도록 한다. backpropagation이 parameter의 scale에 영향을 받지 않도록 만들기 때문이다.</li>
<li>수식적으로 살펴 보았을때,</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/569ec88d-0efc-4aee-b0ce-3fbfe8f0d66d/Untitled.png" alt="Untitled"></p>
<p>이렇게 parameter의 scaling factor가 gradient 값에 영향을 미치게 되지 않는 것을 확인할 수 있고, 즉 learning rate의 크기에 따라 gradient 값의 크기가 달라져 문제가 생기지 않을 것임을 확인할 수 있다.</p>
<h3 id="34-batch-normalization-regularizes-the-model">3.4 Batch Normalization regularizes the model</h3>
<ul>
<li>Batch Normalization을 사용하게 되면, 훈련 과정에서 batch 내의 다른 instance에 대한 정보가 평균과 분산 등의 통계값으로 포함되게 된다. 따라서 이로 인해 특정 sample에 대한 network의 의존성이 줄어들고, 더욱 일반화되는 효과를 기대할 수 있다.</li>
<li>실험 결과, 실제로 Batch Normalization이 overfitting을 막아주는 regularization 역할을 한다는 것 역시 확인할 수 있었다.</li>
</ul>
<h2 id="4-experiments">4. Experiments</h2>
<h3 id="41-activations-over-time">4.1 Activations over time</h3>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/29a3c8c4-c39e-418f-b98d-65b8fac9d92b/Untitled.png" alt="Untitled"></p>
<ul>
<li>위 이미지는 간단한 MNIST dataset classification을 BN을 사용하여 진행했을때 어떻게 달라지는지에 대한 분석을 담고 있다.</li>
<li>Batch Normalization을 사용하였을 때 성능이 더 좋게 나왔다. 이 원인을 분석하고자 BN을 사용하지 않았을 때와 사용하였을때의 sigmoid에 들어가는 input을 조사해보았더니, BN을 사용하지 않았을 때에는 분포가 시간에 다라 달라지는 것이 보이나, BN을 사용하였을때에는 비교적 일관된 분포를 유지하는 모습을 볼 수 있었다.</li>
</ul>
<h3 id="42-imagenet-classification">4.2 ImageNet classification</h3>
<ul>
<li>Inception Network에 Batch Normalization을 추가하여 ImageNet classification을 진행해보았다.</li>
</ul>
<p>4.2.1 Accelerating BN Networks</p>
<ul>
<li>Inception 모델에 BN을 추가한 후, 저자는 learning rate를 상승시키고, Dropout을 제거하였으며, L2 regularization을 줄이고 learning rate decay을 증가시켰다.</li>
<li>또한 local response normalization을 제거하였고, traning data를 더욱 shuffle 시켰으며, photometric distortion을 줄였다.</li>
</ul>
<p>4.2.2 Single Network Classification</p>
<ul>
<li>그 후 Inception 모델, 거기에 BN을 추가한 모델, BN을 추가하고 learning rate를 5배 높인 모델, 30배 높인 모델 등을 각각 이미지넷 데이터에 대해 학습시켰다.</li>
<li>그 결과는 다음과 같다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9b06b5b9-cd21-4946-85f9-703ae43c0460/Untitled.png" alt="Untitled"></p>
<ul>
<li>BN을 사용하였을때, 그렇지 않았을 때보다 절반 이하의 training step만에 동일한 정확도에 도달하였다.</li>
<li>BN을 사용한 후 learning rate를 5배 높였을 때에는, 유사한 정확도에 도달하기까지 14배 적은 step이 걸렸다.</li>
<li>BN을 사용한 후 30배의 learning rate를 사용하였을 때에는, 유사한 정확도에 도달하기까지 5배 적은 step이 걸리고, 최종적으로는 원래 모델보다 2.6% 더 높은 정확도를 기록하였다.</li>
</ul>
<p>4.2.3 Ensemble Classification</p>
<ul>
<li>이 논문이 나오기 전까지 ImageNet Classification에 대한 최고 성능은 여러 모델을 Ensemble하여 얻은 결과로, 4.94%의 Error를 기록하였다. 해당 논문에서, 6개의 모델에 BN을 적용하여 Ensemble을 한 결과, 4.82%의 Error를 기록하여 이전 최고 성능을 뛰어넘었다.</li>
</ul>
<h2 id="5-conclusion">5. Conclusion</h2>
<ul>
<li>본 논문에서는 딥러닝의 학습 속도를 빠르게 하기 위한 방법으로 Batch Normalization을 고안하였다.</li>
<li>이 방법은 딥러닝의 학습을 복잡하게 만드는 원인인 Internal Covariate Shift 를 줄이고자 고안된 방법으로, stochastic gradient learning 을 사용하는 각 layer의 input을 mini batch의 평균과 분산을 사용해 normalize하는 방법이다.</li>
<li>이를 통해 학습의 속도도 더 빠르게 할 수 있으며, 더 높은 learning rate를 사용 가능하게 되었고, 학습의 성능 역시 좋아지는 모습을 보였다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] U-Net]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-U-Net</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-U-Net</guid>
            <pubDate>Tue, 30 May 2023 16:59:06 GMT</pubDate>
            <description><![CDATA[<h1 id="u-net--convolutional-networks-for-biomedical-image-segmentation">U-Net : Convolutional Networks for Biomedical Image Segmentation</h1>
<ul>
<li>해당 논문에서는 데이터 증강을 사용하여 주어진 의료 이미지를 효과적으로 학습시키는 네트워크와 학습 전략을 고안하였다.</li>
<li>네트워크의 구조는 context를 처리하기 위한 constracting path와 정확한 localization이 가능하도록 하는 대칭된 expanding path로 구성되어있다. 또한 그 사이의 skip connection 역시 존재한다.</li>
<li>논문에서는 neuronal sturcture에 대한 segmentation task에서, 해당 네트워크를 사용하여 적은 수의 이미지로도 효과적이고 강력한, 심지어 빠른 end to end learning을 할 수 있음을 보인다.</li>
</ul>
<h2 id="segmentation">Segmentation</h2>
<ul>
<li>최근 다양한 CNN 모델들이 등장하였고 좋은 성능을 내고 있는데, CNN은 일반적으로 classification task에 쓰이고 있다. classification의 output은 하나의 class label이다.</li>
<li>반면, 다양한 visual task에서, 특히 의료 이미지에서는 localization을 포함한 output을 필요로 한다. 즉, class label이 각 pixel에 대해 부여되어야 한다.  즉 segmentation을 필요로 한다.</li>
<li>기존에 최고 성능을 내던 연구에서는 sliding window 방식을 사용하여 각각의 pixel 주변의 local region(patch)에 대해 class label을 예측하도록 네트워크를 학습시켰다.</li>
<li>이렇게 하면 network가 localize도 수행할 수 있을 뿐더러, 학습 데이터, 즉 patch가 학습 이미지의 수에 비해 훨씬 많아지는 효과도 존재한다.</li>
<li>하지만 이러한 방법은 명백하게 두개의 약점을 가지고 있다. 먼저, network가 각 patch에 대해서 동작해야 하므로 매우 느리다는 것과, 각 patch 사이에 겹치는 부분이 많아 중복이 많이 발생한다는 것이다.</li>
<li>두 번째는 localization accuracy와 use of context 사이의 trade off 문제이다. large patch를 사용하면 max pooling layer를 더 많이 사용해야 하므로 localization accuracy가 줄어들지만, small patch를 사용하면, 네트워크가 localization은 더 잘 해내는 반면, 작은 문맥 정보밖에 사용하지 못한다.</li>
<li>따라서 이를 해결하기 위해 최근의 방법들은 multiple layer의 feature를 사용하여 classifier가 output을 만들어내도록 하고 있기도 하다.</li>
</ul>
<h2 id="model-architecture">Model Architecture</h2>
<ul>
<li>해당 논문에서는 fully convolutional network를 사용하여 segmentation을 위한 network를 고안한다.</li>
<li>FCN을 수정하고 확장하여 적은 수의 학습 이미지로도 정확한 segmentation을 해내는 모델을 만들 것이다.</li>
<li>기존 FCN의 메인 아이디어는, 일반적인 CNN(contracting path) 뒤에 pooling operator 대신 upsampling opertor를 사용한 레이어를 추가하는 것이었다. upsampling 레이어를 거친 output의 해상도는 증가할 것이다.</li>
<li>따라서 high resolution feature와 contracting path의 feature들을 함께 사용하여 사용한다면 convolution layer가 더 정확한 localization을 해낼 수 있었다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/9d243869-0933-4b7d-b752-5785ac6588a6/image.png" alt=""></p>
<ul>
<li>U-Net에서는 이러한 FCN을, upsampling part에서도 많은 수의 feature channel을 가지도록 수정하였다. 이를 통해 네트워크가 higher resolution layer에 context 정보를 전달할 수 있도록 하였다.</li>
<li>그 결과로써, contracting path와 대칭되는, expansive path가 생기게 되었고, 네트워크는 U자형 형태를 가지게 되었다.</li>
<li>Fig 1.에서 네트워크 architecture를 살펴보면, 왼쪽 부분의 contracting path와 오른쪽 부분의 expansive path를 확인할 수 있다.</li>
<li>contracting path는 일반적인 convolutional network의 형태를 가지고 있어, 2개의 3x3 convolution layer 뒤에 relu function 이 적용되고, 2x2 max pooling이 stride 2로 적용되어 downsampling 된다.</li>
<li>이를 통해 각각의 downsampling step에서 channel 수를 2배로 늘리고, size를 줄여가며 convolution을 진행해 세부적인 feature를 뽑아낸다.</li>
<li>expansive path는 feature map을 2x2 upconvolution을 통해 upsampling 한 후, contracting path에서의 feature map과 concatenate하여 2개의 3x3 conv layer 및 relu 함수를 적용시킨다. 이를 통해 맥락에 대한 정보를 얻어낸다.</li>
<li>이때, convolution 과정을 거치며 가장자리 pixel들이 사라졌기 때문에, concatenate를 위해서는 contracting path의 feature map을 cropping 해야만 한다.</li>
<li>마지막 layer는 1x1 convolution으로, 64 channel의 feature map을 class의 개수에 맞는 channel수를 가지도록 만들어준다.</li>
<li>따라서 전체 네트워크는 23개의 convolutional layer를 가지고 있다.</li>
</ul>
<h2 id="training">Training</h2>
<ul>
<li>논문에서는 SGD를 사용하여 훈련을 진행하였고, 훈련에 있어 GPU memory를 최대한 사용하기 위해 large input tile과 large batch size를 사용하였고, high momentum(0.99)을 사용하여 이전 training sample들의 optimization에서의 영향을 크게 하였다.</li>
<li>loss function(energy function)은 cross entropy function과, final feature map에서의 pixelwise softmax를 결합하여 계산한다.</li>
<li>softmax function은 해당 pixel의 feature map의 각 채널에서의 activation 중 해당 class를 나타내는 channel의 확률을 나타낸다. 따라서 정답 class에서는 1이고, 나머지 채널에 대해서는 0이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/8cd936db-b78c-4cba-9e3b-e553718f1c4b/image.png" alt=""></p>
<ul>
<li>cross entropy도 살짝 변형하여 사용하는데, 기존 cross entorpy와는 달리 확률값에 로그를 씌운 값에 weight map w를 곱한 값의 합이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/f85702db-900d-4c47-9a8b-4a05b7210546/image.png" alt=""></p>
<ul>
<li>또한 이는 인접한 세포들 사이의 작은 seperation border를 잘 학습하기 위해서도 사용되는데, 이를 위해 인접한 cell과의 거리에 따른 가중치를 부여하는 방식으로 다음과 같이 계산된다. wc는 class freqeuncy의 균형을 맞춰주기 위해 ground truth를 토대로 미리 계산된 weight map이다.</li>
<li>뒤의 항은 가장 가까운 cell과 두번째로 가까운 cell의 경계까지의 거리 d1, d2를 포함하고 있다. 논문에서는 w0 = 10, 시그마 = 5pixel을 사용하였다. 이를 통해 인접한 세포와의 거리가 가까운 pixel에 대해 더 큰 가중치를 부여하여 small seperation border를 더 잘 학습할 수 있도록 하였다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/3990c77c-c182-42e8-a93c-eafff11bcf49/image.png" alt=""></p>
<ul>
<li>initial weights는 네트워크의 각각의 feature map이 unit variance를 가지도록 초기화되었다. 이는  weights를 표준편차를 $\sqrt{2/N}$으로 하는 gaussian distribution으로부터 초기화함으로써 얻어내었다. 여기서 N은 하나의 뉴런에 대해 incoming node의 수이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/b4576a8d-5320-4446-a629-c120bbfe481f/image.png" alt=""></p>
<ul>
<li>U-Net은 overlap tile strategy를 사용하여 매끄러운 segmentation이 진행될 수 있도록 한다.</li>
<li>overlap tile strategy는 입력 이미지를 겹쳐지는 부분이 존재하는 여러 개의 타일로 나누고, 각 타일에 대해 segmentation을 진행한 후 이를 조합하여 최종 segmentation map을 만드는 방법이다.</li>
<li>input의 size가 output의 size보다 크므로, input의 가장자리에 있는 pixel에 대한 예측을 진행하기 위해서, input image를 mirroring 함으로써 missing context를 extrapolation 시켜준다. 이를 통해 경계부분에 대한 segmentation 성능을 높일 수 있다.</li>
<li>큰 사이즈의 이미지는 GPU memory의 한계로 인해 작은 사이즈로 resizing 될 것이기 때문에, 이미지를 여러개의 tile로 나누어 처리하는 overlap tile strategy가 매우 중요한 기법이다.</li>
</ul>
<h2 id="data-augmentation">Data Augmentation</h2>
<ul>
<li>training sample의 수가 적을 때, 네트워크가 invariance하고 robust하게 하기 위해서는 data augmentation이 필수적이다.</li>
<li>의료 이미지 task에서는 아주 적은 training data를 사용가능하다. 따라서, traning image에 대해 elastic deformation(비선형적인 변환)을 통해 추가적인 data augmentation을 진행하였다. 이를 통해 network가 그러한 변형에 대해서도 불변하도록 학습시켰다.</li>
<li>구체적으로는, 이미지를 3x3 grid로 나누어 각각의 grid에 대해 random displacement를 진행하였다.</li>
<li>세포 조직에 대해서 실제로 가장 자주 일어나는 변형이 deformation이기 때문에, 이는 biomedical segmentation에 있어 아주 중요하다.</li>
</ul>
<h2 id="experiments">Experiments</h2>
<ul>
<li>neronal sturctures in electorn microsocpic recordings을 segmentation 하는 task에서 최고의 성능(warping error, rand error, pixel error)을 내었다.</li>
<li>또한 두개의 다른 task에서도 최고 성능(IOU)을 내었다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Pointpillars: Fast Encoders for Object Detection from Point Clouds]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Pointpillars-Fast-Encoders-for-Object-Detection-from-Point-Clouds</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Pointpillars-Fast-Encoders-for-Object-Detection-from-Point-Clouds</guid>
            <pubDate>Wed, 05 Apr 2023 15:49:09 GMT</pubDate>
            <description><![CDATA[<p>음 몇번째 논문이지?
한 네번째 되는 것 같다.
이제는 조금 빨라진 것 같기도 하고 아닌것 같기도 하고.</p>
<p>어쨌든 읽다보면 기초를 다시 탄탄히 해야겠음을 느낀다. 정말로!</p>
<hr>
<h1 id="pointpillars-fast-encoders-for-object-detection-from-point-clouds">PointPillars: Fast Encoders for Object Detection from Point Clouds</h1>
<h2 id="abstract">Abstract</h2>
<ul>
<li>해당 논문에서는 point cloud를 down stream detection pipeline에 적절한 형태로 encoding 하는 문제에 대해 다룬다.</li>
<li>최근의 논문들은 1. fixed encoder(빠르지만 정확도가 낮음), 2. 학습된 인코더(느리지만 정확도가 높음)의 두가지 형태의 인코더들을 주로 제안하고 있다.</li>
<li>이 논문에서는, PointNet을 활용하여 pointcloud를 vertical columns(pillars)로 인코딩하는 PointPillars라는 새로운 encoder를 제시한다.</li>
<li>PointPillars를 통해 인코딩된 feature는 다른 인코더를 사용한 결과와는 다르게 2D convolution에 적용될 수 있다.</li>
<li>해당 인코더를 사용하여 실험한 결과, 3D와 Brid Eye View의 속도와 정확성 측면에서 모두 SOTA를 찍었다. 실행시간은 2~4배 개선되었다.</li>
</ul>
<aside>
💡 PointPillars는 Point cloud를 Pillars(수직 기둥들)로 인코딩하는 새로운 방법을 제시한다.
이를 통해 피쳐가 2D convolution에 사용될 수 있도록 하였고, 그 결과 속도가 매우 향상되었으며 성능도 좋았다.

</aside>

<h2 id="introduction">Introduction</h2>
<ul>
<li>CV분야가 매우 발전함에 따라, object detection 기술을 lidar point cloud에 얼마나 적용할 수 있는지에 대한 연구가 계속 진행되어왔다.</li>
<li>이미지와 point cloud간의 큰 차이는 1.  image는 dense하고, point cloud는 sparse 하다는 것과 2. image는 2d이고, point cloud는 3d라는 것이다.</li>
<li>따라서 일반적인 image convolutional pipeline만으로는 point cloud에서의 object detection을 잘 해낼 수 없다.</li>
<li>그래서 몇몇의 연구들은 point colud의 image로의 projection 또는 3D Convolution의 사용에 집중했다.</li>
<li>최근의 방법들은 point cloud를 Bird’s Eye view에서 바라보는 방법을 많이 사용한다. 이러한 방법은 물체의 scale 정보를 유지시켜주고, occlusion을 감소시킨다는 장점이 있다.</li>
<li>그러나, 이러한 BEV를 CNN에 직접 사용하기에는 너무 sparse하여 효과적이지 않다.</li>
<li>이 문제에 대한 해결으로써, ground plane을 regular grid로 나누어 각각의 gird에 hand crafted feature encoding을 진행하는 방법도 고안되었으나, 일반화되기 쉽지 않다는 단점이 있다.</li>
<li>VoxelNet은 3d object detection 분야의 첫 end to end 모델로, 공간은 voxel로 나누고, 각각의 voxel에 PointNet을 적용하여 feature encoding을 한 후, 3d convolutional middle layer를 지난 후 RPN을 적용해 3d detection을 진행한다.</li>
<li>이는 성능은 좋지만, real time detection에 사용하기에는 너무 느리다.</li>
<li>최근에는 SECOND가 등장하여 속도를 올렸으나, 여전히 3D convolution을 사용하기에 느린 점이 있다.</li>
</ul>
<aside>
💡 3d detection 분야의 발전 현황.
일반적인 image와 달리 3d이며 sparse 하다는 특징이 존재하여, 여러 방법 중 BEV와 3D Convolution을 사용하는 방법이 사용되고 있다.
최근 VoxelNet의 등장으로 end to end model이 등장하였고, SECOND가 속도를 많이 향상시켰으나 이는 여전히 real time task에 적용하기에 매우 느리다.(3D Convolution 때문)

</aside>

<ul>
<li>이 논문은 2D convolutional layer만 가지고 3d object detection 을 진행하는 end-to-end 학습 모델인 PointPillars를 제안한다.</li>
<li>PointPillars는 vertical column인 pillar로 공간을 나누고, 이 pillar를 통해 feature를 학습하여 3d oriented box를 예측하는 새로운 형식의 인코더이다.</li>
<li>PointPillars는, fixed encoder를 사용하지 않고 pillar를 학습하여 feature encoding을 진행함으로써, pointcloud에 표현된 전체 정보를 활용할 수 있다.’</li>
<li>voxel이 아니라 pillar를 사용함으로써, vertical direction을 직접 나누어주지(binning) 않아도 된다.</li>
<li>pillars는 2D convolution에 사용될 수 있기 때문에 매우 빠르고 효율적이다.</li>
<li>PointPillars는 KITTI Dataset에 대해 3D, BEV에서 모두 최고 성능을 내었다.</li>
</ul>
<aside>
💡 PointPillars의 특징 및 장점에 대해 이야기하고 있다.
1. PointPillars는 공간을 Pillar로 나누어 이로부터 특징을 학습하는 새로운 인코더이다.
2. 이는 vertical binning을 직접 진행하지 않아도 되고, 2D Convolution에 활용할 수 있어 매우 빠르고 효율적이다.

</aside>

<h3 id="11-related-work">1.1. Related Work</h3>
<h3 id="111-object-detection-using-cnns">1.1.1 Object Detection using CNNs</h3>
<ul>
<li>RCNN으로부터 object detection에 CNN을 사용하려는 시도가 시작되었다.</li>
<li>Faster R-CNN은 RPN의 등장으로 two stage detector를 발전시켰다.</li>
<li>SSD와 같은 single stage detector는 anchor box들을 1stage regression을 통해 분류하여 빠르고 간단한 detection을 진행한다.</li>
<li>Focal loss 함수에서, single stage method가 two stage method보다 실행 속도와 성능이 모두 좋다는 연구 결과가 있었다.</li>
<li>따라서 PointPillars에서는 1 stage detector를 head로 사용한다.</li>
</ul>
<h3 id="112-object-detection-in-lidar-point-clouds">1.1.2 Object Detection in lidar point clouds</h3>
<ul>
<li>3D convolution network를 3d detection에 사용하려는 시도들이 있어왔다.</li>
<li>하지만 매우 느리다는 단점이 존재한다.</li>
<li>최근의 방법들은 3D point cloud를 ground 혹은 image plane에 투영하여 실행 시간을 개선하려는 시도를 하였다.</li>
<li>가장 많이 사용되는 방법은 point cloud를 voxel로 나누고, 각각 vertical column의 voxel들을 fixed length의 hand crafted feature encoding을 진행해 pseudo image를 만들어 standard image object detection을 진행하는 방법이다. (MV3D, AVOD, PIXOR 등)</li>
<li>그 후 PointNet의 등장으로, pointcloud에서 직접 학습하여 특징을 추출할 수 있는 방법이 생겼고, VoxelNet이 end to end model로써 3d object detection을 진행한다.</li>
<li>VoxelNet에서 PointNet은 voxel에 적용되고 3D Convolutional layer, 2D backbone, detection head의 과정을 거쳐 처리된다.</li>
<li>3D Convolution이 적용되므로, 속도는 매우 느리다.</li>
</ul>
<h3 id="12-contributions">1.2. Contributions</h3>
<ul>
<li>새로운 방식의 point cloud encoder Point pillars를 제안하여, end to end training 과 3d object detection을 할 수 있는 새로운 방법을 제시한다.</li>
<li>pillars에서의 모든 계산은 dense 2D convolution으로 제시될 수 있고, 이는 다른 방법들에 비해 2~4배 빠른 요소이다.</li>
<li>KITTI dataset에서 SOTA를 찍었다.</li>
</ul>
<h2 id="2-pointpillars-network">2. PointPillars Network</h2>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fa815b69-ed2d-4308-aed1-b16a85a061fc/Untitled.png" alt="Untitled"></p>
<p>PointPillars의 network는 다음과 같은 3단계로 구성된다.</p>
<ol>
<li>A feature encoder network : that converts a point cloud a sparse pseudo-image</li>
<li>a 2D convolutional backbone : to process the pseudo-image into high-level representation</li>
<li>a detection head : that detects and regresses 3D boxes</li>
</ol>
<h3 id="21-pointcloud-to-pseudo-image">2.1. Pointcloud to Pseudo-image</h3>
<ul>
<li><p>pointcloud를 2D convolution에 사용하기 위해서는 이를 pseudo-image로 변환해야한다.</p>
</li>
<li><p>따라서 Pointpillars의 첫번째 단계는 pseudo image를 만들기 위한 feature encoder이다.</p>
</li>
<li><p>먼저 point cloud는 x-y 평면의 grid로 세분화되어 각각 grid의 pillar로 만들어진다.</p>
</li>
<li><p>각각의 pillars는 x,y,z,r 뿐 아니라 pillar에 있는 x,y,z 각각의 산술 평균($x_c, y_c, z_C$<em>), 그리고 각 pillar의 중심점 좌표(</em>$x_p, y_p$<em>)</em>를 포함하고 있는 9차원(D)의 정보를 가진다.</p>
</li>
<li><p>point cloud가 매우 sparse하기 때문에, pillar들도 대부분 비어있을 것이고, 비어있지 않은 pillar들의 경우도 몇개의 점밖에 갖고 있지 않을 것이다.</p>
</li>
<li><p>sample당 non empty pillars의 개수(P)에 제한을 두고, pillar당 point의 개수(N)에 제한을 두어서 이러한 sparsity를 해결하고, (D,P,N) size의 tensor를 만든다.</p>
</li>
<li><p>즉, sample이나 pillar가 너무 많은 point를 가지면 random sampling하고, 너무 적으면 zero padding한다.</p>
</li>
<li><p>그 후 각각의 point에 PointNet의 간단한 버전을 사용하여 BN, ReLU를 지나게해 (C,P,N)size의 feature tensor를 만든다. channel에 대해 max pooling을 진행하여 (C,P) size의 output tensor가 되게 한다.</p>
</li>
<li><p>이렇게 feature encoding이 되고 난 후, feature들은 다시 원래의 pillar location으로 scatter되어 (C,H,W) size의 pseudo - image를 만든다.</p>
</li>
</ul>
<aside>
💡 Feature Encoder의 경우, 
각각의 점들을 Pillar로 나누어주고, PointNet을 사용하여 Feature를 추출한 후, 이 feature를 scatter하여 pseudo image를 만든다.

</aside>

<h3 id="22-backbone">2.2. Backbone</h3>
<ul>
<li><p>VoxelNet에서와 유사한 구조의 backbone을 사용한다.</p>
</li>
<li><p>즉, top-down network와 deconvolutional network 두 개의 network로 구성되어 있다.</p>
</li>
<li><p>top down network는 여러개의 (S,L,F) Block 들로 이루어져 있는데, 각각의 블록에서는 (S) stirde를 하고, L개의 3x3 2D conv를 지나며, BN과 ReLU를 포함하는 F output channel이 존재한다.</p>
</li>
<li><p>block layer의 첫 번째 conv만 ${{S}/{S_in}}$의 stride를 가지며 그 후 conv들은 stride 1을 가진다.</p>
</li>
<li><p>deconv network는 각각의 top-down block의 feature들을 upsampling하고 concatenate하여 final feature를 얻어낸다.</p>
</li>
<li><p>이는 transposed 2D convolution, BN, ReLU를 통해 진행된다.</p>
</li>
<li><p>결국 final output feature는 서로 다른 stride를 통해 얻어진 모든 feature들의 종합이다.</p>
</li>
</ul>
<aside>
💡 Backbone의 경우,
VoxelNet에서와 유사하게 여러개의 2D Conv block을 지나고, 
각각의 block을 Deconv하여 high resolution feature들의 concatenation feature를 얻는다.

</aside>

<h3 id="23-detection-head">2.3. Detection Head</h3>
<ul>
<li>Detection Head로는 single stage detector인 Single Shot Detector(SSD)를 사용한다.</li>
<li>3D Detection에 사용하기 위해 height와 elevation을 추가로 regression 한다.</li>
</ul>
<aside>
💡 Detection Head의 경우,
SSD에 height와 elevation을 추가하여 사용한다.

</aside>

<h2 id="3-implementation-details">3. Implementation Details</h2>
<h3 id="31-network">3.1. Network</h3>
<ul>
<li>network의 parameter들은 pre-train된 값을 사용하지 않고, 랜덤 값을 이용하여 초기화하였다.</li>
<li>encoder network는 C = 64의 output feature를 가진다.</li>
<li>car, pedestrian/cyclist는 각각 S =2. S =1의 stride값을 가진다.</li>
<li>top down backbone network는 Block1(S, 4, C), Block2(2S, 6, 2C), and Block3(4S, 6,4C)로 구성</li>
<li>deconv는 Up1(S, S, 2C), Up2(2S, S, 2C) and Up3(4S, S, 2C)로 구성</li>
<li>최종적으로 concatenated된 output feature는 6C개의 feautre를 가지게 된다.</li>
</ul>
<aside>
💡 앞서 살펴본 network에 실제로 사용된 parameter 값들에 대해 다루고 있다.

</aside>

<h3 id="32-loss">3.2. Loss</h3>
<ul>
<li>SECOND에서 도입된 Loss function과 같은 loss를 사용한다.</li>
<li>localization regression residual은</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5879feb9-51ba-4609-8cbd-113322c4e9e5/Untitled.png" alt="Untitled"></p>
<pre><code>    다음과 같이 표현된다.</code></pre><ul>
<li>$x^{gt}$와 $x^a$는 각각 ground truth와 anchor box의 값이고, d는 대각선의 길이를 의미한다.</li>
<li>total locatization loss는 smoothL1 loss를 사용한다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0c184023-f14d-4deb-8868-76cc2b0f05dc/Untitled.png" alt="Untitled"></p>
<ul>
<li>angle localization loss로는 flipped된 box를 구별하지 못하므로, 이를 막기 위해 방향을 이산화하여 구분할 수 있는 softmax classfication loss를 사용한다.</li>
<li>classification loss는 focal loss를 사용한다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c20fe269-cb49-412c-8998-778cfbe8ff1e/Untitled.png" alt="Untitled"></p>
<ul>
<li>따라서 최종적인 Loss 함수는 다음과 같다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b66191e0-a937-488b-80f7-2309d4187101/Untitled.png" alt="Untitled"></p>
<ul>
<li>optimizer로는 Adam을 사용하였고, 0.0002의 lr로 시작하여 15 epochs마다 0.8씩 decay하여 160 epoch를 학습하였다.</li>
<li>validation set에서는 batch size = 2, test submission에서는 4로 사용하였다.</li>
</ul>
<aside>
💡 Loss 함수로는, 
smoothL1을 사용한 localization loss, 
softmax를 사용한 angle localization loss,
focal loss를 사용한 classification loss의 가중합을 사용한다.

</aside>

<h2 id="4-experimental-setup">4. Experimental setup</h2>
<h3 id="41-dataset">4.1. Dataset</h3>
<ul>
<li>KITTI Dataset을 사용한다. lidar point clouds와 image sample들로 구성되어 있다.</li>
<li>car, pedestrian, cyclist를 detection 해야한다.</li>
</ul>
<h3 id="42-settings">4.2. Settings</h3>
<ul>
<li>2D IOU를 사용한다.</li>
<li>match threshold를 넘으면 positive, negative threshold이하면 negative, 둘 다 아니면 무시한다.</li>
<li>IOU 0.5를 기준으로 NMS를 적용한다.</li>
</ul>
<h3 id="43-data-augmentation">4.3. Data Augmentation</h3>
<ul>
<li>KITTI에 있어 Data augmentation은 아주 중요하다.</li>
<li>SECOND에서와 마찬가지로, 모든 class에 대한 ground truth 3D box의 lookup table을 만든 후, 임의로 선택된 gt sample들을 current point cloud에 위치시킨다.</li>
<li>그 후 모든 gt box들을 augmentation 시킨다. 회전 및 이동을 진행한다.</li>
<li>마지막으로 point cloud와 box에 대해 random flip, global rotation, scaling을 진행한 후 global translation을 진행한다.</li>
</ul>
<h2 id="5-results">5. Results</h2>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/44c7d09a-de9c-4229-b165-8f5612354bfd/Untitled.png" alt="Untitled"></p>
<h3 id="quantitative-analysis">Quantitative Analysis.</h3>
<ul>
<li>mAP에 있어 가장 좋은 성능을 낸다.</li>
<li>Lidar Only만 사용하는 방법들 중에서는 easy car를 제외하고 모든 부문에서 최고 성능을 내었다.</li>
</ul>
<p><img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b720b486-c92f-4817-9600-defce00b7bd7/Untitled.png" alt="Untitled"></p>
<h3 id="qualitative-anaylsis">Qualitative Anaylsis</h3>
<ul>
<li>위 Figure들은 bbox 예측 결과를 BEV와 image에 나타낸 것이다.</li>
<li>car에 대한 예측 중 오류의 대부분은 false negative on difficult samples이거나 유사한 class에 대한 false positive이다.</li>
<li>보행자와 자전거를 탐지하는것은 더 어려운데, 서로 각각 잘못 분류되는 경우가 많았다.</li>
</ul>
<aside>
💡 3d detection 모델들 중 최고 성능을 내었고, 속도도 아주 많이 단축시켰다.

</aside>

<h2 id="6-realtime-inference">6. Realtime Inference</h2>
<ul>
<li><p>앞선 Table에서 볼 수 있듯이, PointPillars는 예측 시간에 있어 매우 큰 향상을 보여준다.</p>
</li>
<li><p>따라서 pointpillars의 과정 중 어느 부분이 빠른 것인지를 분석하여 보았다.</p>
</li>
<li><p>main inference step은 다음과 같다.</p>
<ul>
<li>point cloud loading and filtering(1.4ms)</li>
<li>points are organized in pillars(2.7ms)</li>
<li>PointPillar tensor uploaded to the GPU(2.9ms)</li>
<li>encoding(1.3ms)</li>
<li>scatter to pseudo-image(0.1ms)</li>
<li>processed by the backbone and detection heads(7.7ms)</li>
<li>NMS on CPU(0.1ms)</li>
</ul>
</li>
<li><p>이를 통해 runtime이 빨라질 수 있던 가장 큰 이유는 PointPillar encoding임을 알 수 있었다.</p>
</li>
<li><p>VoxelNet의 encoder는 190ms가 걸리는데 비해, 1.3ms의 시간은 아주 빠르다.</p>
</li>
<li><p>SECOND의 encoder조차도 50ms가 소요된다.</p>
</li>
<li><p>VoxelNet에서는 2개의 sequential PointNet이 사용된데에 비해 여기서는 하나만 사용되었고, 이 역시 시간을 줄일 수 있던 원인이다.</p>
</li>
<li><p>이 외 output dimension을 줄이는 등 slimmer design 을 통해 속도를 빠르게 하였다.</p>
</li>
</ul>
<aside>
💡 PointPillars는 다른 3d detection 모델들에 비해 아주 빠른 속도로 실행된다.
이는 Encoding에 3D Conv가 사용되지 않아 소요되는 시간이 짧기 때문이다.

</aside>

<h2 id="7-ablation-studies">7. Ablation Studies</h2>
<h3 id="71-spatial-resolution">7.1. Spatial Resolution</h3>
<ul>
<li>binning size를 작게하면 속도는 떨어지지만 성능을 올라간다.</li>
<li>speed 와 accuracy 간의 trade off를 binning size로 조절할 수 있다.</li>
<li>pillar가 크면, non empty pillar가 적어지고 smaller pseudo image가 만들어지므로 빠르다.</li>
<li>pillar가 작으면, 더 정밀한 localization과 많은 feature를 얻을 수 있어 정확하다.</li>
</ul>
<h3 id="72-per-box-data-augmentation">7.2. Per Box Data Augmentation</h3>
<ul>
<li>minimal box augmentation에서의 성능이 더 잘 나왔다.</li>
<li>특히, pedestrian의 detection에 있어 box augmentation을 진행할수록 성능이 떨어졌다.</li>
</ul>
<h3 id="73-point-decorations">7.3. Point Decorations</h3>
<ul>
<li>VoxelNet에서 점의 좌표를 7dimension으로 표시했던 반면, pointpillars에서는 xp와 yp까지 9 dimenstion을 사용했다.</li>
<li>이러한 Decoration이 0.5 mAP의 성능 향상을 가져왔따.</li>
</ul>
<h3 id="74-encoding">7.4. Encoding</h3>
<ul>
<li>PointPillar Encoder가 아닌 SECOND 등의 Encoder를 사용하여 성능을 측정해보았다.</li>
<li>fixed encoder보다 learned encoder의 성능이 더 좋았다.</li>
<li>VoxelNet의 Encoder가 PointPillars보다 성능이 좋았으나, 시간의 차이가 많이 나기에 PointPillars가 더 좋은 인코더로 보여진다.</li>
<li>조건을 더욱 통제하여 추가 연구가 필요할 것으로 보인다.</li>
</ul>
<h2 id="8-conclusion">8. Conclusion</h2>
<ul>
<li>이 논문에서는 point cloud에 사용될 수 있는 end to end deep network이자 encoder인 PointPillars를 고안하였다.</li>
<li>KITTI dataset에서 전까지 존재하던 모델 중 가장 좋은 성능과 가장 빠른 속도를 보였다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Visualizing and Understanding Convolutional Networks : ZFNet]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Visualizing-and-Understanding-Convolutional-Networks-ZFNet</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Visualizing-and-Understanding-Convolutional-Networks-ZFNet</guid>
            <pubDate>Wed, 29 Mar 2023 17:46:18 GMT</pubDate>
            <description><![CDATA[<p>세번째 논문 리뷰.
사실 이번주 너무 바쁘고 정신없고 스트레스 받아서.
좀 쉽게 가려고 했는데 생각보다 많이 어려웠다.
그래서 더 스트레스 받은건,,,</p>
<p>그래도 열심히 읽고 정리해보았다...
파이팅..!</p>
<hr>
<h1 id="visualizing-and-understanding-convolutional-networks--zfnet">Visualizing and Understanding Convolutional Networks : ZFNet</h1>
<ul>
<li>2013년 발표된 논문.</li>
<li>ILSVRC 대회에서 AlexNet에 이어 우승을 차지한 모델</li>
<li>모델 자체의 구조는 AlexNet과 크게 달라지지 않았고, 논문의 제목에서 볼 수 있듯이 시각화 기법을 도입해 CNN의 동작 원리를 이해하는데 초점을 맞춘 논문이다.</li>
</ul>
<h1 id="abstract">Abstract</h1>
<ul>
<li>Image classification에 있어 CNN은 좋은 성능을 내고 있다.</li>
<li>그러나, CNN이 어떤 방식으로 동작하는지, 왜 좋은 성능을 내는지에 대한 명확한 이해는 이루어지고 있지 않다.</li>
<li>본 논문에서는 새로운 시각화 기술을 도입하여 convolutional layer의 feature를 시각화하여 convolutional network가 어떻게 동작하는지 이해하고, 더 좋은 모델 구조를 고안한다.</li>
<li>또한 classifier에 대한 실험을 진행해 CNN이 어떻게 동작하는지 더 깊은 이해를 제공한다.</li>
<li>마지막으로 ImageNet 데이터로 학습한 feature가 다른 데이터 셋에도 일반화여 사용될 수 있음을 보인다.</li>
</ul>
<h1 id="1-introduction">1. Introduction</h1>
<ul>
<li>2012년도 ILSVRC에서 AlexNet이 우승하면서, CNN이 복잡한 이미지 분류 문제에 좋은 성능을 낼 수 있음을 보였다.</li>
<li>매우 큰 데이터셋이 생기고, GPU의 계산 성능이 강력해지고, dropout 같은 regularization 방법이 발전하면서 CNN이 재발견 되었다.</li>
<li>그러나 CNN이 어떻게 내부에서 동작하고 좋은 성능을 내는지는 알려져 있지 않다.</li>
<li>따라서 이 논문에서는 Deconvolutional Network를 사용한 새로운 시각화 기법을 도입하여 input Image가 모델 내부의 feature map을 어떻게 활성화시키는지를 시각화한다.</li>
<li>추가적으로 학습이 진행되는 동안 feature가 어떻게 학습되는지 과정 역시 시각화하고, 이를 통해 모델의 어느 부분을 개선해야 성능이 더 좋아질지에 대해 고민한다.</li>
<li>그리고, Input Image의 특정 부분들을 가린 채 classification을 진행해보며 CNN에서 classification이 어떻게 진행되는지에 대한 분석 역시 진행한다.</li>
</ul>
<h2 id="11-related-work">1.1. Related Work</h2>
<ul>
<li>여태까지 feature를 Input Image Pixel space에 투영하여 시각화하려는 시도는 대부분이 첫 번째 층의 레이어에서만 진행되었다.</li>
<li>높은 층의 layer에서는 그러한 방법이 작동하지 않았고, Hessian등을 사용한 몇몇 수치적 계산 방법으로만 feature가 어떻게 형성되는지에 대한 대략적인 이해를 제공하였다.</li>
<li>본 논문에서는 이러한 문제를 해결하기 위해 비모수적인 방법을 사용해 Input pixel space에 feature map을 투영하여, 이미지의 어떤 부분이 feature map을 활성화시키는지 시각화한다.</li>
</ul>
<h1 id="2-approach">2. Approach</h1>
<ul>
<li>AlexNet의 Convolutional layer 구조를 먼저 살펴보면, convolution → relu → max pooling 의 순서로 이루어져있다.</li>
</ul>
<h2 id="21-visualization-with-a-deconvnet">2.1. Visualization with a Deconvnet</h2>
<ul>
<li><p>CNN의 작동 방식을 이해하기 위해서는 각 layer에서 feature map이 어떻게 activation되는지에 대한 해석을 해야한다.</p>
</li>
<li><p>따라서 논문에서는 이러한 activation들을 input pixel space로 매핑시켜, 어떤 input pattern이 해당 activation을 유발했는지를 보여주는 방법을 제시한다.</p>
</li>
<li><p>앞에서 Conv → relu → Max pooling의 과정으로 이어지는 AlexNet의 동작방식을 언급하였는데, 이와 정확히 반대의 과정을 수행함으로써 activation을 input space에 매핑시킨다.</p>
</li>
<li><p>이는 Deconvnet 을 통해 이루어진다.</p>
</li>
<li><p>각각의 convolutional layer에 해당하는 만큼 deconvnet을 부착한다고 생각하면 된다.</p>
</li>
<li><p>원하는 activation을 input space에 매핑시키기 위해서, feature map의 다른 activation은 모두 0으로 만든 후 feature map을 deconvnet에 통과시킨다.</p>
</li>
<li><p>deconvnet에서는 unpooling → rectify → deconvolution을 거친다.</p>
</li>
<li><p>연속된 여러 deconvnet layer를 거쳐 목표로 하는 activation을 input space에 매핑시킬 수 있다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/d874f987-7f84-4377-9699-1c9868910b9a/image.png" alt=""></p>
<ul>
<li>Deconvnet에서 일어나는 연산들을 조금 더 자세히 살펴보자.</li>
</ul>
<h3 id="unpooling">Unpooling</h3>
<ul>
<li>Max Pooling의 역 연산에 해당하는 것이 바로 Unpooling이다.</li>
<li>하지만 Max pooling은 여러 값들 중 최대값만을 남기는 연산이므로 완벽한 역연산을 수행할 수 없다.</li>
<li>따라서 역연산을 위해 switch라는 방법론을 도입하는데, 이는 pooling이 일어나는 과정에서 최대값의 위치를 기록하는 방법이다.</li>
<li>각각의 pooling region에서의 최대값의 위치를 swtich를 통해 알고 있으므로, unpooling에서는 해당 위치에 pooling 된 값들을 매핑시키고, 나머지 위치는 0으로 채워준다.</li>
<li>이를 통해 원래 input의 위치 정보 및 이미지 구조가 보존된 상태로 unpooling을 진행할 수 있다.</li>
</ul>
<h3 id="rectification">Rectification</h3>
<ul>
<li>Activation function인 ReLU의 역연산에 해당하는 부분이다.</li>
<li>ReLU는 양수인 값들만 남기는 활성함수이므로, 역연산에서도 단지 ReLU 그대로를 적용해준다.</li>
<li>이렇게하면 음수인 값들을 복원하지 못하는 문제가 발생하지만, 결과에 큰 영향을 미치지 않는다.</li>
</ul>
<h3 id="filtering">Filtering</h3>
<ul>
<li>convolution layer에서는 filter들에 대해 이미지와 convolution 연산을 수행한다.</li>
<li>이 과정의 역연산을 위해서, filter를 transpose 시킨 transpose filter들과 이미지를 convolution 연산한다.</li>
<li>convolution 연산을 filter를 sparse matrix로 만들어 이미지와 행렬 곱 하는 연산과 동일하게 생각할 수 있기 때문에, transpose와 filtering 해준다면 역연산을 하는 효과가 있다.</li>
</ul>
<h1 id="3-training-details">3. Training Details</h1>
<p>논문에 사용된 모델과 학습 방법에 대해서 설명하고 있다. AlexNet과 대체적으로 유사하지만, 하나의 차이점은 layer 3,4,5 사이에 사용된 sparse connections이다. (2개의 GPU에서 연산을 진행하기 때문에) ZFNet에서는 이 sparse connection을 dense connection으로 변경하였다.</p>
<p>모델은 imagenet 2012 training set에 대해 학습되었고, 각각의 RGB image는 256*256의 사이즈로 resizing 되었다. mini batch size 128의 stochastic gradient descent 방법이 사용되었고, 0.01의 learning rate로 시작하였다. momentum의 값은 0.9이다. dropout 역시 fully connected layer에 0.5의 비율로 사용되었다. 모든 weights는 0.01의 값으로 초기화되었다.</p>
<p>Fig 6.(a)를 보면 알 수 있듯이, 첫번째 layer의 filter를 시각화해보면 그들 중 아주 일부만이 dominate 함을 알 수 있다. 즉, 몇개의 필터만이 다른 필터에 비해 매우 높은 값을 가진다. 이러한 상황은 모델의 효율성을 감소시킬 수 있으므로, 이를 해결하기 위해 필터의 RMS vlaue가 0.1의 범위를 초과하는 필터를 0.1로 normalize 시킨다. 이것은 특히 모델의 첫번째 층에 있어서 매우 중요한 과정이다. 모델의 효율성을 저하시키는 것을 방지하고, 각 필터의 크기를 조절하여 모델이 더욱 효과적으로 학습하도록 한다. </p>
<h1 id="4-convnet-visulization">4. Convnet Visulization</h1>
<h3 id="feature-visulization">Feature Visulization</h3>
<ul>
<li>모델을 학습하고 앞서 언급한 시각화 기법을 사용하여 시각화를 진행하였다.</li>
<li>주어진 feature map의 상위 9개 activation에 대해서 deconvolutional network를 통해 input space로 매핑한 결과와 해당 부분에 해당하는 input image의 patch를 시각화하였다.</li>
<li>network의 깊이에 따라 계층적인 구조를 띄고 있음을 확인할 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/a40e19db-8e62-46e0-a15e-34d17f95aa00/image.png" alt=""></p>
<ul>
<li>layer 1과 2에서는 주로  corner, edge, 색상에 반응을 하고 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/f395f324-eab2-4906-8e8f-51229b94c9b1/image.png" alt=""></p>
<ul>
<li>layer 3에서는 mesh pattern과 같은 비교적 더 복잡한 texture에까지 반응을 하고 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/cbebb900-cddf-4891-b85c-b8f87c96419c/image.png" alt=""></p>
<ul>
<li>layer 4와 5에서는 더욱 구체적인 형상에 반응하여, 개의 얼굴, 새의 다리 등의 class specific한 feature와 포즈 변화가 있는 전체 객체에까지 반응을 하는 모습을 확인할 수 있다.</li>
</ul>
<h3 id="feature-evolution-during-training">Feature Evolution during Training</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/335347f5-ffb4-4342-85de-8ef81ff4ca80/image.png" alt=""></p>
<ul>
<li>각 layer에서 epoch에 따라 feature를 시각화한 결과이다.</li>
<li>낮은 층의 layer에서는 몇 에포크만에 feature가 수렴하지만, 높은 층의 layer로 올라갈수록 40 에포크가 넘어가서야 feature가 수렴하는 모습을 확인할 수 있다.</li>
<li>즉 높은 층의 layer에서 더 오랜 시간에 걸쳐 학습이 이루어진다.</li>
</ul>
<h3 id="feature-invariance">Feature Invariance</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/dc0b65d4-d674-4bea-9e80-9c256960e939/image.png" alt=""></p>
<ul>
<li><p>5개의 샘플 이미지를 각각 이동, scaling, rotation 하여 원래 feature와의 차이를 나타낸 그래프이다.</p>
</li>
<li><p>layer가 낮을때에는 작은 이미지 변형도 큰 영향을 끼치지만, layer가 높아짐에 따라서 점차 영향이 줄어든다.</p>
</li>
<li><p>결론적으로는 translation과 scaling에 대해서는 output에 영향이 존재하지 않았다.</p>
</li>
<li><p>다만 rotation의 경우 원래 회전에 대해 대칭적인 물체들을 제외하고는 영향이 존재하였다.</p>
</li>
<li><p>여기까지 ZFnet을 통해 시각화한 feature들에 대해 살펴보았다.</p>
</li>
<li><p>높은 activation에 대해 해당하는 위치와 filter를 찾아내어 거꾸로 연산해 반대로 input space에 투영시킨 결과들을 보았다고 생각하면 될 것 같다.</p>
</li>
<li><p>결과적으로는 낮은 layer에서는 색상, edge 등과 같은 단순한 feature를 학습하였고 높은 layer로 올라갈수록 구체적인 물체의 형상이 학습된다는 사실을 알 수 있었다.</p>
</li>
</ul>
<h3 id="41-architecture-selection">4.1. Architecture Selection</h3>
<ul>
<li>이러한 feature 시각화를 통해 모델의 어떤 부분에 문제가 있으며, 어떻게 개선해야할지를 알아볼 수 있다.</li>
<li>아래 figure에서 보면 첫번째 layer에서 stride 4로 filtering을 진행한 탓에 feature에 aliasing이 발생함을 확인하였다.</li>
<li>따라서 이를 해결하기 위해 ZFNet은 AlexNet의 첫번째 layer의 filter size를 11 x 11에서 7 x 7로 줄이고, stride 역시 2로 줄였다.</li>
<li>이를 통해 첫번째와 두번째 레이어의 feature가 더 많은 정보를 가질 수 있게 하여 classification 성능에 개선을 가져올 수 있었다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/7fc6f3a4-5335-45b3-bff1-5e6b77cd4ddf/image.png" alt=""></p>
<h3 id="42-occlusion-sensitivity">4.2. Occlusion Sensitivity</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/2a717008-d2d6-4d8c-8033-f153ed6ad3a5/image.png" alt=""></p>
<ul>
<li>앞에서 언급하였다시피, 해당 논문에서는 input image의 특정 부분을 가리면서 classifier가 어떻게 동작하는지를 확인하는 실험 역시 진행하였다.</li>
<li>이는 CNN이 어떻게 동작하는지를 조금 더 이해하기 위한 실험인데, 맥락만을 활용하여 classification을 수행하는지, 혹은 정확한 물체의 위치를 찾아내어 classification을 수행하는지를 확인하기 위한 실험이다.</li>
<li>해당 figure는 input image의 특정 부분을 가려가며 실험을 진행한 결과이다.</li>
<li>먼저 (c)는 해당 input image에 대해 최상단의 convolutional layer에서 가장 강력한 feature map을 deconvnet을 이용해 시각화한 결과이다. 강아지의 얼굴이 가장 강력한 feature로 추출되었음을 확인할 수 있다.</li>
<li>(b)는 해당 input image의 가린 부분을 옮겨가며 feature map의 활성도를 나타낸 것인데, 강아지의 얼굴 부분을 가렸을 때 activation이 확 떨어지는 모습이다.</li>
<li>(d)는 input image에서 가린 부분을 옮겨가며 classification이 정답일 확률을 나타낸 것인데, 강아지의 얼굴 부분을 가렸을 때 확률이 가장 떨어짐을 볼 수 있다.</li>
<li>(e)는 각 부분을 가렸을 때 classification의 예측 결과를 나타낸 것인데 역시 강아지의 얼굴 부분을 가렸을 때에만 다른 class로 예측함을 확인할 수 있다.</li>
<li>즉, CNN이 강아지의 얼굴이라는 강력한 feature를 학습하여 이미지에서 해당 feature에 해당하는 부분을 찾아내 classification을 수행한다는 것을 확인할 수 있다.</li>
<li>또한, 강아지의 얼굴이 가장 강력한 feature였고, 해당 부분을 가렸을 때 여러 반응이 일어난다는 점에서 feature의 시각화가 제대로 이루어졌음을 확인할 수 있다.</li>
</ul>
<h3 id="43-correspondece-analysis">4.3. Correspondece Analysis</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/935dd32c-7d5e-4036-b8ef-b628272c2361/image.png" alt=""></p>
<ul>
<li>해당 실험은 CNN 모델이 서로 다른 이미지에서 물체의 특정 부분간의 대응을 어떻게 인식하는지를 알아보기 위한 실험이다.</li>
<li>예를 들어 얼굴은 눈과 코의 조합으로 이루어져 있는데, 딥러닝 모델이 이를 계산하는지 아닌지에 대해 알아본다.</li>
<li>이를 위해 5개의 서로 다른 강아지 이미지에 동일한 특정 부위(ex : 왼쪽 눈)를 가린 후 featuer vector를 얻어내고, 원래의 feature vector와의 차이를 계산한다.</li>
<li>그 후 각 이미지 간 그 차이를 Hamming distance로 계산하여, 그 값이 작다면 왼쪽 눈을 가렸을때 서로 다른 각 이미지들에서 feature가 달라진 방식이 유사하다는 것을 의미한다.</li>
<li>실험 결과 5번째 레이어에서 낮은 점수를 기록해, CNN 모델이 특정 물체를 구성하는 부분간의 대응을 계산함을 알 수 있었다.</li>
</ul>
<h2 id="5-experiments">5. Experiments</h2>
<h3 id="51-imagenet-2012">5.1. ImageNet 2012</h3>
<ul>
<li>AlexNet보다 성능이 1.7% 향상되어 14.8%의 error rate를 가졌다.</li>
</ul>
<h3 id="52-feature-generalization">5.2. Feature Generalization</h3>
<ul>
<li>ImageNet 데이터로 학습한 feature들을 사용하여 Caltech-101과 Caltech-256 데이터셋에서도 좋은 성능을 얻었다.</li>
<li>해당 feature를 일반화하여 다른 dataset에도 사용할 수 있음을 확인하였다.</li>
</ul>
<h3 id="53-feature-analysis">5.3. Feature Analysis</h3>
<ul>
<li>ImageNet으로 학습된 레이어의 수를 다르게 하며 caltech dataset에 대해 평가를 진행하였더니, layer의 수가 많을수록 좋은 성능을 내었다.</li>
<li>network의 hierachy가 깊어질수록 더 강력한 feature를 학습함을 알 수 있다.</li>
</ul>
<h2 id="6-conclusion">6. Conclusion</h2>
<p>본 논문에서는 Image Classification을 위한 CNN에 대해 여러 방향에서 탐색해보았다.</p>
<p>먼저, 모델 안에서 일어나는 활동들을 시각화하기 위한 새로운 방법을 고안하였다. 이를 통해 feature가 직관적으로 알아볼 수 있는 객체를 표시한다는 사실을 알게되었으며, layer가 높아질수록 더욱 불변성있고 클래스간 구분이 가능한 특징들을 학습함을 보여준다. 또한, 이러한 시각화를 더 좋은 성능을 얻기 위해 모델을 디버깅하는 수단으로도 활용하여, AlexNet의 성능을 개선하기도 하였다. </p>
<p>또한, 이미지의 일부를 가려보는 실험을 통하여 이미지가 단지 넓은 장면의 상황정보만을 활용하여 classification 되는 것이 아니라, 지역적인 특징에 민감하게 반응한다는 사실을 확인할 수 있었다.</p>
<p>마지막으로, ImageNet에 대해 train된 모델들이 다른 데이터셋에도 잘 일반화하여 사용될 수 있음을 보였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문읽기] Yolo v1]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Yolo-v1</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Yolo-v1</guid>
            <pubDate>Wed, 22 Mar 2023 16:03:11 GMT</pubDate>
            <description><![CDATA[<p>두 번째로 살펴본 논문은 1-stage detector의 대표적인 model인 YOLO 이다.
가장 첫 모델인 Yolo v1부터 살펴보는 것이 맞을 것 같아서 이 논문을 읽어보게 되었다. 
지난번에 한번 읽어보았으니,,, 지난번보단 빨리 읽을 수 있겠지?
파이팅해보자~!</p>
<p>영어가 안되가지고 해석이 너무 힘들었다...
오늘은 블로그에 정리되어 있는 논문 리뷰 글을 읽은 후 논문을 읽어보았다.
<a href="https://bkshin.tistory.com/entry/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-YOLOYou-Only-Look-Once">참고한 블로그</a>
그랬더니 그나마 좀 읽힌다...
파이팅!</p>
<hr>
<h1 id="you-only-look-once-unified-real-time-object-detection">You Only Look Once: Unified, Real-Time Object Detection</h1>
<h2 id="abstract">Abstract</h2>
<ul>
<li>이전 object detection 기술들은 detection을 수행하기 위해 <em>classifier</em>를 여러번 사용하였다.</li>
<li><strong>YOLO</strong>는, object detection을 공간적으로 나눠진 bounding box들과 관련된 class 확률들의 <em>regression</em> problem으로 처리한다.</li>
<li>하나의 network가 bounding box와 class 확률을 전체 이미지에서 한번에 예측한다. </li>
<li>전체 detection과정이 하나의 네트워크 안에서 일어나는 end-to-end 모델로써 최적화에 좋다.</li>
<li>속도 역시 YOLO는 1초에 45frame을, Fast YOLO는 1초에 155 frames를 처리할 수 있을 정도로 빠르다.</li>
<li>SOTA 모델들보다 localization error는 더 많이 발생하지만, background의 false positive는 줄어들었다.</li>
<li>또한, natural image 뿐 아니라 artwork 같은 다른 도메인에서도 우수한 성능을 보인다.</li>
</ul>
<h2 id="1-introduction">1. Introduction</h2>
<ul>
<li>한번에 보고 인지하는 사람의 시각 시스템이 빠르고 정확하기 때문에 사람은 다양한 일을 할 수 있다. 만약 컴퓨터가 그렇다면? 아주 다양한 가능성이 열릴것이다.</li>
<li>현재의 object detection system : 물체를 인식하기 위해서, 시스템은 classifier를 가지고 이미지의 여러 부분을 평가해야만 한다.</li>
<li>DPM과 같은 모델은 sliding window 방식을 사용하여 심지어 빈 공간에조차 classifier를 작동시켜야 한다.</li>
<li>더 최근의 방식인 R-CNN은 먼저 물체가 있을 것으로 예상되는 region proposal을 만들어 낸 후, 이 proposal 들에만 classifier를 작동시킨다. classification 후에, bounding box를 더 잘 예측하기 위한, 중복된 detection을 제거하기 위한 후처리도 필요하다.</li>
<li>이러한 과정은 너무 복잡하여 느리고, 각각의 학습 과정이 개별적으로 일어나기 때문에 최적화하기에도 힘들다.</li>
<li>따라서 이 논문에서는, object detection을 single regression problem 으로 단순화한다.</li>
<li>image pixel에서 bounding box 좌표와 class 확률을 직접 regression 한다.</li>
<li>이러한 방식으로, 어떤 물체가 어디에 존재하는지 detection 하기 위해서 이미지를 &#39;한번만 본다.&#39;</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/3b868ee5-27e4-47f4-9657-23a673f236c5/image.png" alt=""></p>
<ul>
<li>YOLO는 아주 단순하다. 위의 figure를 보면, 하나의 convolutional network가 동시에 여러 bounding box와 그 box들의 class probabilites를 예측하고 있다. </li>
<li>YOLO는 전체 이미지에 대해서 학습을 진행하고, detection performance를 토대로 즉각적인 최적화를 시행한다. 이 unified 된 모델은 object detection 의 기존 모델에 비해 여러 장점을 가지고 있다.</li>
<li>먼저, 아주 빠르다. object detection 과정을 regression problem 으로 여기기 때문에, 마지막에 classifier를 사용해야 하는, 그러한 류의 복잡한 과정이 존재하지 않는다. 그냥 단순히 네트워크 하나를 작동시키면 될 뿐이다. YOLO는 실험에서 초당 45 frame 의 이미지를 처리하였고,  Fast YOLO는 150프레임까지 처리하기도 하였다. 이것은 우리가 video와 같은 real-time  이미지를 거의 지연 없이 처리할 수 있음을 의미한다.</li>
<li>다음으로, YOLO는 이미지 전체를 통해 예측을 진행한다. sliding window나 region proposal 같은 방법과 달리, YOLO는 학습이 진행되는 동안 image 전체를 다루고 있다. 따라서 이미지 전체에 대한 문맥적인 정보를 즉각적으로 반영할 수 있다. Fast R-CNN은 이러지 못하므로 background를 object로 잘못 인식하는 경우가 많은데, YOLO는 과정동안 이미지 전체를 다룸으로 이러한 문제를 해결한다.</li>
<li>세번째로, YOLO는 물체의 일반적인 표현을 잘 학습한다. natural image 를 통해 학습하여 artwork 에서 test를 진행했을 때, YOLO는 DPM과 R-CNN 같은 방법들보다 더 좋은 성능을 내었다. 따라서 새로운 도메인이나 예측하지 못한 input에 더 잘 대응할 수 있다.</li>
<li>그러나 YOLO는 SOTA에 비해 accuracy가 떨어진다. 빠르게 물체를 인식하는 동안 정확히 물체의 위치를 파악하는데, 특히 작은 물체에 대해 어려움을 겪는다.</li>
</ul>
<h2 id="2unified-detection">2.Unified Detection</h2>
<ul>
<li>이전까지 여러 단계로 나누어져 있던 object detection의 요소들을 하나의 neural network로 unify 하였다.</li>
<li>entire image로부터 추출된 feature를 사용하여 bounding box를 예측한다. 또한 모든 bounding box에 대해 모든 class에 대한 확률을 동시에 계산한다.</li>
<li>즉, network가 이미지 전체와 이미지 내의 모든 물체들에 대해 근거를 두고 있음을 의미한다. </li>
<li>이로 인해 YOLO는 end-to-end 방식의 학습과 높은 정확도를 겸비한 real time speed를 가능하게 하였다.</li>
</ul>
<p>그렇다면 YOLO의 동작 과정에 대해서 살펴보자.</p>
<ul>
<li><p>YOLO는 input image를 $S \times S$ 의 grid로 나눈다. 어떤 물체의 중심이 어떤 grid cell 안에 있으면, 그 grid cell이 그 물체를 감지하는데 책임이 있다.</p>
</li>
<li><p>각각의 grid cell에선 B개의 bounding box와 그 box들에 대한 confidence score를 예측한다. 이 confidence score는 bbox에 물체가 있고 어떤 물체인지가 얼마나 정확한지에 대한 신뢰도를 나타낸다. 각각의 bbox는 x,y,w,h,confidence의 5개 정보로 구성된다. confidence는 결국 예측된 box와 ground truth box 사이의 IOU * 클래스로 분류될 확률을 의미한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/7d35020a-9e4e-4960-ab3d-10f1c71d094b/image.png" alt=""></p>
</li>
<li><p>또한 각각의 grid cell에서는 또한 C개의 conditional class probabilities를 예측한다. 이 확률들은 grid cell이 물체를 포함하고 있다는 가정하의 조건부 확률이며, 각 grid cell에서의 bbox의 수와 상관 없이 1세트의 class probabilites만 예측한다.</p>
</li>
<li><p>test 과정에서는 conditional class probabilities와 indeividual box confidence predictions를 곱한다. 이는 각각의 bbox별로 class specific confidence를 제공한다. 해당 점수는 box안에 나타난 물체의 class에 대한 확률과 bbox가 얼마나 물체에 잘 맞게 형성되었는지에 대한 정보를 가지고 있다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/cfd0e253-4cbd-4b0d-9a5d-fa79435675ef/image.png" alt=""></p>
<ul>
<li>이러한 과정을 거쳐서 나온 output은 tensor 형태를 띠는데, $S \times S \times (B *5 + C)$ size의 tensor가 된다.</li>
<li>B * 5 의 의미? 각 bbox가 5개의 정보를 담고있다.</li>
</ul>
<h3 id="21-network-design">2.1. Network Design</h3>
<p>그럼 이제 Yolo의 Network Design에 대해서 살펴보자.</p>
<ul>
<li>첫번째 convolutional layer는 image에서 feature를 추출하고, Fc가 output probabilities와 coordinates를 계산한다.</li>
<li>네트워크 구조는 GoogLeNet model의 구조를 사용하였다. 24개의 convolutional layer와 2개의 Fc layer가 있다. GoogLeNet에서는 inception modules를 사용하였지만, 여기서는 간단한 3X3 convolutional layer 뒤에 1X1의 reduction layer를 사용함으로써 계산을 줄였다. </li>
</ul>
<h3 id="22-training">2.2 Training</h3>
<ul>
<li>먼저 20개의 Convolution layer를 ImageNet data에 대해 pretrain 하였다. 그 후 detection을 수행하기 위해 4개의 convolutional network와 2개의 fully connected network를 추가하였다. 또한, 좋은 해상도의 이미지에 대해 detection이 더 잘 작동하므로 input size를 224 x 224에서, 448 x 448로 바꾸었다.</li>
<li>마지막 layer가 bbox의 좌표와 class probabilites를 모두 예측하는데, bbox의 너비와 높이, 중심점의 좌표는 0~1의 값을 가지도록 normalize하였다. </li>
<li>activation function으로는 leaky relu 함수를 사용하였다. 함수는 다음과 같다. 
<img src="https://velog.velcdn.com/images/im_ngooh/post/4f15d596-35bd-4a1f-9055-25bfd0355dd6/image.png" alt=""></li>
<li>모델을 평가하기 위한 loss로는 SSE(Sum Squared Error)를 사용하였다. 이는 optimize 하기 쉽기 때문이다. 다만, 이를 최적화하는 것이 mAP를 높이는 것을 보장하지는 않는다. SSE의 경우 localization error를 classficiation error와 동일하게 가중치를 두는데, 이는 이상적이지 않다. 또한, 이미지에서 상당수의 grid cell들은 object를 가지고 있지 않은 background이다. 이러한 cell들의 confidence score를 모두 0로 만드는 것은 object를 포함하고 있는 cell들에 비해 너무 많은 가중치를 부여하게 된다. 이는 모델의 불균형으로 인한 불안정성을 유발할 수 있다.</li>
<li>이를 해결하기 위해서, bbox 좌표 예측에 대한 loss는 큰 가중치를 부여하고(bbox 좌표가 있다는 것은 일단 물체가 존재한다는 뜻. 이 loss에 가중치를 부여한다면 background가 너무 많아 생기는 데이터 불균형 문제에 대한 해결책이 될 수 있는 것 같다), 물체를 가지고 있지 않은 box의 confidence loss에 대해서는 작은 가중치를 부여한다. 이를 위해 $\lambda_{coord} = 5$ 와 $\lambda_{noobj} = 0.5$를 사용한다.</li>
<li>SSE가 가지는 또 다른 문제는 large box와 small box의 loss에 같은 가중치를 부여한다는 것이다. error metric은 large box에서의 작은 편차를 small box에서보다 덜 중요하게 여겨야 한다고 한다. 왜? 당연히 클수록 조금만 움직여도 움직인 절대적 크기는 커질거니까. 같은 거리를 움직였어도 큰 박스가 움직인 것과 작은 박스가 움직인것의 중요도는 다를 수 밖에 없다. 따라서 이를 해결하기 위해 bbox의 width와 height에 root를 취해준다. </li>
<li>YOLO는 grid cell 하나마다 여러개의 bbox를 예측한다. 학습을 시킬때에는 하나의 bbox가 각각의 물체에 책임이 있기를 원한다. ground truth와 IOU가 가장 높은 값을 가지는 bbox에 대해 한 물체에 책임을 지게 한다. 이것은 bbox 사이의 구분(specialization)을 이끌어낸다. 각각의 bbox는 특정 사이즈, 비율, 클래스 예측을 더 잘 해내게 된다.</li>
<li>학습을 시키는 동안 다음과 같은 loss function을 사용한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/c8c336c0-06f1-4072-b263-eb32ddd5afd7/image.png" alt=""></li>
<li>식을 보면, classification error의 경우 해당 grid cell안에 물체가 존재할때만 penalize 하고 있다. 
마찬가지로, bbox의 좌표에 대해서는 해당 bbox가 ground truth box에 responsible 할 때, 즉 IOU가 가장 높아 해당 물체의 예측을 담당할때에만 penalize 하도록 하고 있다.<blockquote>
<p>식의 의미를 조금 더 살펴보자.</p>
</blockquote>
먼저 첫번째와 두번째 line은 localization loss계산을 담당하는 부분이다. 해당 부분에서는 해당 물체를 예측하는 bbox predictor의 coordinate에 대한 loss를 계산한다. 앞에서 언급한바와 같이 $\lambda_{coord}$를 통해서 큰 가중치를 두어 loss를 계산하는 모습을 살펴볼 수 있으며, width 와 height는 root를 씌워서 scaling 한 모습을 확인할 수 있다.<blockquote>
</blockquote>
세번째와 네번째 line은 confidence loss를 담당하는 부분인데, 물체가 존재하는 bbox predictor에 대해서는 그냥 SSE를 더해주고, 물체가 존재하지 않는 bbox에 대해서는 $\lambda_{noobj}$를 곱하여 더해줌으로써 적은 가중치만 두는 모습을 확인할 수 있다.<blockquote>
</blockquote>
마지막으로 다섯번째 줄은 물체가 존재하는 bbox에 대해서 class probabilites의 loss를 계산해주는 term이라고 볼 수 있을 것이다.<blockquote>
</blockquote>
움 약간 의문이라면, 3와 4 line의 confidence loss를 계산하는 부분과 5 line의 class probabilites loss를 계산하는 부분이 약간 겹치는거 아닌가? 다르다. 마지막은 classfication 자체의 loss를 계산한다고 볼 수 있다. 분류기의 (yolo에서는 회귀로 동작하지만) 성능을 높이기 위한 loss인 것이다.</li>
<li>training 과정에서 PASCAL VOC 2007, 2012 data에 대해 135 epoch의 학습을 진행하였고, batch size 는 64, momentum은 0.9, weight decay는 0.0005를 적용하였다.</li>
<li>lr scheduler의 경우 첫번째 epoch에서는 lr을 0.001에서 0.01까지 천천히 상승시켰다. 높은 lr로 학습을 시작하면 unstable gradient로 인해 모델이 자주 diverge(기울기 폭발)하는 모습을 보였다. 이후 0.01의 lr로 75 epochs동안 학습을 진행하였고, 0.001의 lr로 이어서 30 epoch, 마지막으로 0.0001의 lr로 30 epoch의 학습을 진행하였다.</li>
<li>overfitting을 방지하기 위해서 dropout을 사용하였고, data augmentation도 사용하였다. 첫번째 connected layer뒤에 나오는 0.5의 dropout layer는 layer들 사이의 중복 적용을 방지한다. 데이터 증강의 경우 random scaling 과 translation을 적용하였다. </li>
</ul>
<h3 id="23-inference">2.3 Inference</h3>
<ul>
<li>학습에서와 마찬가지로, YOLO는 test image에서의 object detection 역시 하나의 network만 사용한다. </li>
<li>pascal voc dataset에서 네트워크는 이미지 별로 98개(7X7X2)의 bbox와 각 box별 class probabilities를 계산한다. </li>
<li>grid design 은 bbox prediction에 공간 다양성을 적용한다. 특수한 경우에는 물체 하나가 특정 grid cell 하나에 딱 들어가고, network가 그 물체에 대해 하나의 box만 예측하기도 하지만, 큰 물체 혹은 grid의 경계 근처에 있는 물체의 경우, 여러 cell 들에 의해 localize 된다. 이러한 multiple detection을 제거하기 위해서는 Non Maximal Suppresion을 사용한다. </li>
</ul>
<h3 id="24-limitations-of-yolo">2.4 Limitations of YOLO</h3>
<ul>
<li>YOLO는 각 grid cell이 2개의 bbox만 예측하고, 하나의 class 만 가질 수 있게 함으로써 강력한 공간적 제약을 부과한다. 이런 공간적 제약은 모델이 예측할 수 있는 가까이 존재하는 물체들의 수를 제한한다. 따라서 YOLO 모델은 뭉쳐있는 작은 물체들의 group을 detection 하는데에 제한사항을 가진다.</li>
<li>또한 YOLO는 새로운 종횡비나 특별한 외형을 가지는 물체에 대해 일반화하는데에 어려움을 겪으며, 여러 downsampling layer를 거친 후에 예측을 진행하기 때문에 조잡한 feature를 사용한다는 단점도 있다.</li>
<li>그리고, loss function에서 small bounding box와 larege bounding box간의 loss를 동일하게 취급한다는 문제가 있다. 큰 박스의 작은 에러는 일반적으로 괜찮지만 작은 박스의 작은 에러는 IOU에 엄청난 영향을 줄 수 있다. YOLO의 대부분의 error는 incorrect localization에서 온다.</li>
</ul>
<h2 id="3-comparison-to-other-detection-systems">3. Comparison to Other Detection Systems</h2>
<h3 id="dpmdeformable-parts-models">DPM(Deformable parts models)</h3>
<ul>
<li>DPM은 object detecion을 위해 sliding window 기법을 사용한다. feature를 추출하고, 각 region을 분류하고, bbox를 예측하기 위해 연결되지 않은 pipeline을 사용한다. YOLO는 이러한 pipeline을 하나의 single convolutional neural network로 변경하였고, 그 network 하나가 feature extraction, bbox prediction, nms 등을 모두 진행한다. 따라서, DPM은 static feature를 사용하는 반면, YOLO는 feature를 detection task에 맞게 최적화시킬 수 있다. DPM에 비해 YOLO가 더 빠르고 더 정확하다.<h3 id="r-cnn">R-CNN</h3>
</li>
<li>R-CNN은 sliding window가 아닌 region proposals를 사용한다. selective search 방법이 region proposal을 찾기 위해 사용되고, CNN이 feature를 추출하며, SVM이 classification 의 score를 정하고, linear model로 bbox의 위치를 조정한다. 그리고 nms를 사용하여 중복되는 detection을 제거한다. 과정 자체가 복잡하여 매우 느리며, end - to - end가 아니어서 각각의 과정을 tuning 시켜야한다. </li>
<li>YOLO와 R-CNN 사이에 공통점도 존재한다. 각각의 grid cell이 bbox를 제안하고 이 box들을 convolutional feature를 통해 점수를 매긴다는 점이다. 그러나, YOLO가 공간적 제약을 부과하여 동일한 물체에 대해 여러 detection이 생기는 것을 더 방지해준다. yolo는 이미지별로 98개의 bbox만 생성하는데 반해, R-CNN에서는 2000개의 region proposal이 생기게 된다.</li>
</ul>
<h3 id="other-fast-detectors">Other Fast Detectors</h3>
<ul>
<li>Fast R-CNN과 Faster R-CNN은 같은 계산을 공유하고(CNN을 한번만 통과하여 feature사용, end-to-end 방식), region proposal을 만드는 과정을 GPU에서 진행함으로써 R-CNN이 빠르게 동작하도록 만든 것이다. 하지만, 그럼에도 불구하고 여전히 실시간 처리는 불가능한 속도를 제공한다.</li>
<li>YOLO는 거대한 detection pipeline의 각 요소들의 속도를 높이는 대신, pipeline 전체를 버려버리고, 1-stage detector라는 새로운 design 을 창조함으로써 빠른 속도를 이끌어내었다.</li>
</ul>
<h2 id="4-experiments">4. Experiments</h2>
<h3 id="41-comparison-to-other-real-time-systems">4.1 Comparison to Other Real-Time Systems</h3>
<ul>
<li>다른 Real Time Systems로는 30Hz 혹은 100Hz에서 작동하는 DPM 모델이 존재한다. </li>
<li>Fast YOLO는 가장 빠른 object detection method이다. mAP는 52.7%이고, 이는 기존의 real time detection 보다 2배의 정확도를 보여준다. 그냥 YOLO는 mAP가 63.4%로 높다.</li>
<li>YOLO를 VGG-16을 통해서 학습시키면 더 정확하지만 느려진다. </li>
<li>Fastest DPM은 정확도도 상대적으로 낮으며, 속도도 더 느리다.</li>
<li>R-CNN minus R 모델은 selective search를 static bounding box proposal로 변경하였지만, 여전히 느리고 proposal이 좋지 않아 정확도도 낮다.</li>
<li>Fast R-CNN은 R-CNN보다 속도가 높지만, 여전히 selective search를 사용하여 느리다. Faster R-CNN의 경우 RPN을 사용하여 빨라졌지만, YOLO에 비해서 매우 느리다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/0d54fc14-b1f3-4e3f-ae88-c8fe47b8c35d/image.png" alt=""></li>
</ul>
<h3 id="42-voc-2007-error-analysis">4.2 VOC 2007 Error Analysis</h3>
<ul>
<li>YOLO와 다른 SOTA detector들을 더 조사해보기 위해, Error를 더 자세히 살펴보자. Error의 종류는 다음과 같다.
Correct: correct class and IOU &gt; .5
Localization: correct class, .1 &lt; IOU &lt; .5
Similar: class is similar, IOU &gt; .1
Other: class is wrong, IOU &gt; .1
Background: IOU &lt; .1 for any object
이렇게 구분한 Error에 대해서 분석한 결과는 다음과 같다. 
<img src="https://velog.velcdn.com/images/im_ngooh/post/3dd7752a-f101-4331-bbed-cbb7af184849/image.png" alt=""></li>
<li>분석 결과, YOLO는 object를 localize하는데 문제를 겪고 있음을 알 수 있다. YOLO의 대부분의 에러는 localization error이다. Fast R-CNN의 경우 localization error는 적으나, background error, 즉 빈 배경을 물체로 판단하는 경우가 많다.</li>
</ul>
<h3 id="43-combining-fast-r-cnn-and-yolo">4.3 Combining Fast R-CNN and YOLO</h3>
<ul>
<li>그렇다면 서로 다른 장점을 가지고 있는 두 모델을 결합한다면 어떨까?</li>
<li>YOLO를 사용해서 background detection error를 줄일 수 있을 것이다. R-CNN이 예측하는 bbox가 YOLO 역시 비슷하게 예측하는지를 확인함으로써!
<img src="https://velog.velcdn.com/images/im_ngooh/post/9d13f612-05d9-4ff8-9790-5a55353673b8/image.png" alt=""></li>
<li>Fast R-CNN 과 YOLO를 결합해본 결과 mAP 가 상승하는 모습을 확인할 수 있었다. 다만, Fast R-CNN의 다른 모델끼리 결합해본 결과 YOLO와 결합하였을때만큼 성능이 상승하지 않았는데, 이를 통해 Fast R-CNN과 YOLO의 결합은 단순한 ensemble의 효과가 아니라, 서로 다른 error를 가지는 두 모델의 결합으로 인한 성능 상승을 가져옴을 알 수 있다.</li>
</ul>
<h3 id="44-voc-2012-results">4.4 VOC 2012 Results</h3>
<ul>
<li>VOC 2012 test set에 대해서 YOLO는 57.9% mAP를 기록했다.</li>
<li>이는 SOTA보다 낮은 수준으로, 비슷한 순위의 detector들보다 small objects를 감지하는데에 문제가 있었다. </li>
</ul>
<h3 id="45-generalizability--person-detection-in-artwork">4.5 Generalizability : Person Detection in Artwork</h3>
<ul>
<li>학술 연구를 위한 데이터셋의 대부분은 training과 test dataset이 같은 분포를 이루고 있다. 실제 세계에서는 이러기가 거의 불가능하다. </li>
<li>따라서 YOLO를 test함에 있어 picasso dataset과 people art dataset에 적용해보았다. 
<img src="https://velog.velcdn.com/images/im_ngooh/post/2e8c69ef-5b4a-44bd-ad82-64d6997c2aa5/image.png" alt=""></li>
<li>위의 Figure를 보면, YOLO가 다른 모델들에 비해 훨씬 높은 precision과 recall을 보여줌을 알 수 있다.</li>
<li>R-CNN의 경우 selective search가 실제 이미지에 대해 tuning된 방법이기 때문에 artwork 에 대해서 좋은 성능을 내지 못하고 있다.</li>
<li>DPM은 artwork에 적용되었을때에도 정확도가 별로 떨어지지 않는다. 그러나 성능이 좋지 않다.</li>
<li>YOLO는 artwork에 적용되었을때 성능이 떨어지는 정도가 다른 모델들에 비해 적다. 이는 물체의 shape와 size를 모델링하고, 또한 물체사이의 관계와 물체가 주로 나타나는 위치를 모델링하기 때문이다. natural image와 그림은 pixel단위로는 매우 다르지만, 물체의 size와 shape 측면에서는 유사하기 때문에, YOLO가 좋은 성능을 낼 수 있다.(결국 YOLO의 장점이, 물체를 더욱 일반화시켜 학습한다는 것이다.)</li>
</ul>
<h2 id="5-real-time-detection-in-the-wild">5. Real-Time Detection In The Wild</h2>
<ul>
<li>YOLO는 빠르고 정확한 모델이기 때문에, webcam 에 연결하여 real time performance를 확인할 수 있다.</li>
<li>물체가 움직이고 모습이 바뀌어도 detect하는 모습을 확인할 수 있다.</li>
</ul>
<h2 id="6-conclusion">6. Conclusion</h2>
<ul>
<li>YOLO는 object detection을 위한 Unified model, 즉 하나의 네트워크로 이루어진 모델이다.</li>
<li>이 모델은 간단하며, 전체 이미지를 통해 직접적으로 학습할 수 있다. </li>
<li>다른 classifier 기반의 접근 방식과 다르게, YOLO는 loss function을 통해 detection result에서 직접적으로 학습할 수 있고, 전체 모델이 연결되어있다.</li>
<li>Fast YOLO는 가장 빠른 object detector이고, YOLO는 real time detector중 최고 성능을 내고 있다. 또한 새로운 domain의 이미지에 대해서도 잘 일반화해 작동하여 빠르고 강건한 object detection을 위해 사용할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰 스터디] 1회차 : R-CNN]]></title>
            <link>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-%EC%8A%A4%ED%84%B0%EB%94%94-1%ED%9A%8C%EC%B0%A8-R-CNN</link>
            <guid>https://velog.io/@im_ngooh/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-%EC%8A%A4%ED%84%B0%EB%94%94-1%ED%9A%8C%EC%B0%A8-R-CNN</guid>
            <pubDate>Sun, 19 Mar 2023 15:04:46 GMT</pubDate>
            <description><![CDATA[<p>가입한 학회에서 논문 리뷰 스터디에 참여하게 되었다.
논문을 읽어보는 것이 처음이라 많이 겁도 났지만 한번 읽어보았다.</p>
<p>object detection 분야에 대해 아는 것이 없어서 더욱 어려웠던 것 같다.
나의 빈약한 집중력도...! 문제였다.</p>
<p>논문을 읽으면서 chat gpt를 처음 사용해봤는데, 걔 아니었으면 논문 다 읽지도 못할 뻔 했다.
앞으로도 잘 부탁해야겠다...</p>
<hr>
<p>1주차 후기 : 
사람들이 다 천잰가...?
일단 내가 젤 멍청하고 아는게 없다.
윽악
열심히 해야지 뭐,,, 할 수 있겠지..?</p>
<hr>
<h1 id="rich-feature-hierarchies-for-accurate-object-detection-and-semantic-segmentation">Rich feature hierarchies for accurate object detection and semantic segmentation</h1>
<p><a href="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/1311.2524.pdf">Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/1311.2524.pdf</a></p>
<ul>
<li><p>참고 영상 1</p>
<p>  <a href="https://www.youtube.com/watch?v=jqNCdjOB15s&amp;list=PLRx0vPvlEmdADpce8aoBhNnDaaHQN1Typ&amp;index=24">https://www.youtube.com/watch?v=jqNCdjOB15s&amp;list=PLRx0vPvlEmdADpce8aoBhNnDaaHQN1Typ&amp;index=24</a></p>
</li>
<li><p>참고 영상 2</p>
<p>  <a href="https://www.youtube.com/watch?v=kKDJXMZRNe4">https://www.youtube.com/watch?v=kKDJXMZRNe4</a></p>
</li>
<li><p>참고 블로그</p>
<p>  <a href="https://bkshin.tistory.com/entry/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-R-CNN-%ED%86%BA%EC%95%84%EB%B3%B4%EA%B8%B0">논문 리뷰 - R-CNN 톺아보기</a></p>
</li>
</ul>
<aside>
💡 이 논문은 object detection 분야에 큰 발전을 불러온 R-CNN을 설명하는 논문입니다.

</aside>

<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled.png" alt="Untitled"></p>
<h1 id="abstract">Abstract</h1>
<ul>
<li>본 논문에서는 localize and segment objects를 위해 Region proposals에 CNN을 활용하는 방법인 R-CNN에 대해 설명하고 있다.</li>
<li>R-CNN 이라는 이름은 Regions with CNN features를 의미한다.</li>
</ul>
<h1 id="1-introduction">1. Introduction</h1>
<ul>
<li>당시의 상황 : object detection 분야의 기술은 최근 몇 년간 큰 진전이 없었다.</li>
<li>ImageNet 대회의 개최와 AlexNet의 등장으로 CNN에 대한 관심이 높아지고 있었다.</li>
</ul>
<p>⇒ CNN을 object detection에도 사용해보고자 함. ⇒ R-CNN의 등장</p>
<ul>
<li>fine tuning을 진행하였더니 성능이 더욱 잘 나왔다고 한다.</li>
</ul>
<aside>
💡 핵심 1. object detection에 CNN을 사용한 R-CNN
핵심 2. fine tuning을 이용한 성능 향상

</aside>

<h1 id="2-object-detection-with-r-cnn">2. Object detection with R-CNN</h1>
<ul>
<li>R-CNN은 크게 세 단계로 구성된다.<ol>
<li>category - independent region proposlas</li>
<li>large convolution neural network</li>
<li>class specific linear SVMs</li>
</ol>
</li>
</ul>
<h2 id="21-module-design">2.1 Module design</h2>
<h3 id="region-proposals">Region proposals</h3>
<ul>
<li><p>다양한 방법들 가운데, <strong>selective search</strong>를 사용한다.</p>
</li>
<li><p>이는 prior detection work와의 controlled comparison이 가능하게 하기 위해서라고 한다.</p>
  <aside>
  💡 **selective search**란?

<p>  이미지를 일련의 작은 구역으로 분할한 후, 이러한 구역을 합치며 물체가 위치할 가능성이 높은 영역을 식별하는 방법.</p>
<p>  color, texture, size, fill(유사한 주변과의 차이 정도) 4가지 특징을 사용해 유사도가 높은 공간끼리 merge 하며 bottom-up 방식으로 2000개의 Region proposals를 만들어 낸다.</p>
<p>  <img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%201.png" alt="Untitled"></p>
<p>  <a href="http://www.huppelen.nl/publications/selectiveSearchDraft.pdf">http://www.huppelen.nl/publications/selectiveSearchDraft.pdf</a></p>
  </aside>


</li>
</ul>
<h3 id="feature-extraction">Feature extraction</h3>
<ul>
<li>CNN(AlexNet)을 사용하여 각각의 region proposal에 대해 4096 dimensional의 feature vector를 추출해낸다.</li>
<li>더 자세하게는 5개의 convoutional layer와 2개의 fully connected layer를 통과하게 하여 feature를 얻어낸다.</li>
<li>이때 CNN의 input size가 227*227이어야 하므로, 각 region proposal의 사이즈를 변경해줘야 한다.</li>
<li>warping을 통해 각각 region의 이미지 사이즈를 227 * 227로 변환해준다.</li>
</ul>
<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%202.png" alt="Untitled"></p>
<h2 id="22-test-time-detection">2.2 Test-time detection</h2>
<h3 id="test-과정">test 과정</h3>
<ul>
<li>selective search의 fast mode로 2000개의 region proposals 추출</li>
<li>각각의 region을 warp한 후 CNN에 입력하여 feature 추출</li>
<li>각각의 feature들을 각각의 class 하나에 대해 학습되어 있는 SVM에 넣어 점수 획득</li>
<li>이때, greedy non-maximum suppression 방법을 적용<ul>
<li>이는 모든 region에 대해, 점수가 더 높은 region과의 IoU(겹치는 부분)이 특정 임계보다 클 때 해당 region을 제거하는 방법</li>
</ul>
</li>
</ul>
<h3 id="run-time-anaysis">Run-time anaysis</h3>
<ul>
<li>R-CNN은 CNN parameter들이 모든 category에 대해서 공유된다.</li>
<li>해야 할 계산이 selective search, 그리고 SVM에서의 간단한 single matrix - matrix product 밖에 없다.</li>
<li>따라서, 기존의 방법과 달리 아주 효율적이며, 대부분의 CPU에서 빠르게 수행될 수 있다.</li>
</ul>
<h2 id="23-training">2.3 Training</h2>
<h3 id="supervised-pre-training">Supervised pre-training</h3>
<ul>
<li>대규모의 데이터셋(ILSVRC2012 classification)에 대해 먼저 pre-train을 진행한다.</li>
<li>데이터셋에는 bounding box 에 대한 정보는 포함되어 있지 않고, image-level의 label만 존재</li>
<li>pre-trained된 AlexNet을 사용한다</li>
</ul>
<h3 id="domain-specific-fine-tuning">Domain-specific fine-tuning</h3>
<ul>
<li>각각 region proposals에 대해 detection을 수행하기 위해 CNN의 parameter들을 warped region proposals로 fine-tuning 시켜준다.</li>
<li>CNN의 classification layer를 원래 이미지넷 데이터에 맞춰 학습되어 있는 1000-way가 아니라, (N+1)-way의 layer로 바꾸어준 후 학습을 진행하면 된다.</li>
<li>더 자세히는, lr이 0.001인 SGD를 사용하여 학습을 진행하는데, class가 존재하는 32개의 window, 96개의 class가 존재하지 않는 background window로 이루어진 mini batch를 사용하여 학습을 진행한다고 한다. background가 실제로 훨씬 많기 때문에 비율을 그렇게 구성한다.</li>
</ul>
<h3 id="object-category-classifiers">Object category classifiers</h3>
<ul>
<li>물체가 부분적으로 들어가 있는 region을 해결하기 위해 IoU overlap threshold를 정하고, 그 임계값을 넘는 region만 positive로 사용한다.</li>
<li>grid search를 이용해 찾은 최적의 IoU 임계값은 0.3이다.</li>
<li>feature 추출과 training label 부여를 마친 후에는 linear SVM을 최적화한다.</li>
<li>이때 hard negative mining method를 사용했다고 한다.</li>
</ul>
<h2 id="24-results-on-pascal-voc-2010-12">2.4 Results on PASCAL VOC 2010-12</h2>
<ul>
<li>PASCAL VOC : 20개 class에 대해 object detection을 수행하기 위한 데이터셋.</li>
<li>기존 최고 성능인 35.1%에서, mAP가 53.3%까지 상승하는 좋은 성능을 내었다.</li>
<li>같은 region proposal 알고리즘을 사용하는 다른 방법에 비해서도 CNN을 추가한 R-CNN의 성능이 우수하였다.</li>
<li>Bounding box regression을 추가하였을 때, 그렇지 않은 경우보다 성능이 더 높게 나왔다. (추후 appendix C에서 설명됨)</li>
</ul>
<h2 id="25-results-on-ilsvrc2013-detection">2.5 Results on ILSVRC2013 detection</h2>
<ul>
<li>200개의 class에 대한 detection을 수행</li>
<li>24.3% mAP가 가장 좋은 성능이었으나, R-CNN을 사용했을때에는 31.4%로 좋은 성능을 내었다.</li>
</ul>
<h1 id="3-visulaization-ablation-and-modes-of-error">3. Visulaization, ablation, and modes of error</h1>
<h2 id="31-visualizing-learned-features">3.1 Visualizing learned features</h2>
<ul>
<li>추출한 feature, 즉 filter를 어떻게 시각화할 수 있을까?</li>
<li>CNN에서 첫번째 층의 필터는 edge나 보색등을 잡아내므로 이해하기도 쉽고, 시각화도 가능하다.</li>
<li>그러나 층이 깊어질수록 filter를 이해하고 시각화하는데에는 어려움이 있다.</li>
<li>따라서 해당 filter가 어떤 특성을 학습한 것인지 확인하기 위해, 특정 filter 하나하나 각각을 object detector로 사용해 region proposal에 대해 activation을 계산한다.</li>
<li>그 후 가장 높은 점수를 보이는 region을 확인한다면, 해당 filter가 어떤 특성을 학습했는지를 시각화한 셈이 된다.</li>
</ul>
<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%203.png" alt="Untitled"></p>
<ul>
<li>해당 figure는 $pool_5$ layer중 6개 filter를 선택해 각각 높은 activation을 표시한 것이다.</li>
<li>첫번째 필터는 사람의 얼굴, 두번째 필터는 강아지, 세번째 필터는 꽃의 형태를 학습하였을 것임을 예측할 수 있다.</li>
</ul>
<h2 id="32-ablation-studies">3.2 Ablation studies</h2>
<ul>
<li>모델의 구성 요소를 제거하거나 변경하여 해당 기능이 모델의 전반적인 성능에 어떤 영향을 미치는지 평가하는 실험</li>
</ul>
<h3 id="performance-layer-by-layer-without-fine-tuning">Performance layer-by-layer, without fine-tuning</h3>
<ul>
<li>fine tuning 하지 않은 모델을 사용하여 layer별 성능을 평가한 결과, fc layer를 모두 제거하고 사용하였을때 parameter의 수는 6%밖에 되지 않지만, 성능 차이가 크게 나지 않았다.</li>
<li>이를 통해, CNN의 representational power는 convolutional layer에서 온다는 것을 알 수 있었다.</li>
</ul>
<h3 id="performance-layer-by-layer-with-fine-tuning">Performance layer-by-layer, with fine-tuning</h3>
<ul>
<li>fine-tuning의 결과 mAP가 8% 상승하는 것을 볼 수 있었다.</li>
<li>이때, CNN layer에서보다 Fully connected layer에서의 성능 향상폭이 더 컸는데, 이를 통해 ImageNet에서 미리 학습된 CNN layer위에, 특정 데이터로 fine tuning 한 classifier를 사용하였을때 효율적으로 큰 성능 향상을 가져온다는 것을 알 수 있다.</li>
</ul>
<h3 id="comparison-to-recent-feature-learning-methods">Comparison to recent feature learning methods</h3>
<ul>
<li>당시 사용되던 다른 feature learning methods와 비교했을 때 R-CNN이 더 좋은 성능을 낸다.</li>
</ul>
<h2 id="33-network">3.3 Network</h2>
<ul>
<li>AlexNet 대신 VGG16을 CNN model로 사용하였을 때 성능이 8%가량 더 좋게 나왔다.</li>
<li>그러나 연산에 소요되는 시간이 대략 7배 더 길었다고 한다.</li>
</ul>
<h2 id="34-detection-error-analysis">3.4 Detection error analysis</h2>
<ul>
<li>이 논문의 범위를 뛰어넘는다고 표현.</li>
</ul>
<h2 id="35-bounding-box-regression">3.5 Bounding-box regression</h2>
<ul>
<li><p>오차 분석의 결과 localization error를 줄이는 것이 필요하였다고 한다.</p>
</li>
<li><p>따라서 bounding-box의 위치를 linear regression을 통해 찾는 방법을 도입하였다.</p>
</li>
<li><p>각 region proposal을 SVM으로 점수를 매긴 후에, bounding box regressor를 통해 bounding box의 위치를 새로이 예측한다.</p>
</li>
<li><p>더 자세히는, 각 region proposal의 중심점 x,y좌표, 너비와 높이 정보를 가진 P와 실제 bounding box의 해당 정보를 라벨링한 G를 통해 regression을 진행한다.</p>
</li>
<li><p>더 자세히는,,,</p>
</li>
</ul>
<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%204.png" alt="Untitled"></p>
<ul>
<li><p>이렇게 linear한 수식으로 표현 후, 각각의 function d가 CNN feature의 linear function이므로</p>
<p>  <img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%205.png" alt="Untitled"></p>
<p>  이렇게 나타낸 후, ridge regression을 통해 linear regression의 weight를 구한다. </p>
</li>
</ul>
<h1 id="4-the-ilsvrc2013-detection-dataset">4. The ILSVRC2013 detection dataset</h1>
<p>해당 데이터셋이 R-CNN을 적용한 결과를 살펴본다.</p>
<h2 id="41-dataset-overview">4.1. Dataset overview</h2>
<ul>
<li>PASCAL VOC dataset에 비해 클래스 개수도 많고, 이미지도 많다.</li>
</ul>
<h2 id="42-region-proposals">4.2 Region proposals</h2>
<ul>
<li>앞 데이터셋에서와 마찬가지로 selective search의 fast mode를 사용하였다.</li>
<li>다만 이미지의 크기가 모두 제각각이어서 이미지의 크기를 모두 통일해주는 작업을 처음에 진행하였다.</li>
<li>PASCAL 데이터셋에서는 이러한 방법으로 실제 존재하는 bounding box의 98%를 찾아낼 수 있었으나, 해당 데이터셋에서는 91%가량밖에 찾아내지 못하였다.</li>
</ul>
<p>⇒ region proposal stage에서의 개선의 여지가 남아있다.</p>
<h2 id="43-training-data">4.3 Training data</h2>
<ul>
<li>CNN fine-tuning</li>
<li>detector SVM training</li>
<li>bounding-box regressor training</li>
</ul>
<h2 id="45-ablation-study">4.5. Ablation study</h2>
<ul>
<li>CNN fine-tuning + bbox reg set이 성능이 가장 좋았다.</li>
</ul>
<h1 id="5-semantic-segmentation">5. Semantic segmentation</h1>
<aside>
💡 **segmentation**이란?
object detection과 달리, 이미지의 pixel 단위로 객체를 나누어 주는 것을 의미한다.

<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%206.png" alt="Untitled"></p>
<p>이미지 출처 : cs231n 강의자료</p>
</aside>

<ul>
<li>R-CNN을 semantic segmentation에 사용해 보았다.</li>
<li>fine-tuning 없이 진행했을 때, 기존의 방법과 유사한 정도 혹은 살짝 높은 정도의 정확도를 확인할 수 있었다.</li>
</ul>
<p><img src="Rich%20feature%20hierarchies%20for%20accurate%20object%20detec%20f73141abbd59444cbe2751bea06db21b/Untitled%207.png" alt="Untitled"></p>
<h1 id="6-conclusion">6. Conclusion</h1>
<ul>
<li>R-CNN 모델은 성장이 정체되어있던 object detection 분야에서 단번에 성능을 30% 높여준 알고리즘이다.</li>
<li>R-CNN의 핵심은 object detection을 위해서 CNN을 사용했다는 것, 그리고 pre-trained 된 모델에 fine-tuning을 진행하여 사용하는 전이학습 방식을 사용했다는 것이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 59-62] 이미지 전처리]]></title>
            <link>https://velog.io/@im_ngooh/%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A0%84%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@im_ngooh/%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A0%84%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Thu, 08 Dec 2022 08:51:04 GMT</pubDate>
            <description><![CDATA[<p>12.05 ~ 12.07.
CNN에 대해서도 배웠지만, 이미지 전처리도 배웠다. 이 역시 아주 중요한 것 같다.</p>
<hr>
<h1 id="이미지-전처리">이미지 전처리</h1>
<p>CNN에서 이미지 데이터에 대한 분류 예측 문제를 다루어보았다.
이때, 이미지 데이터에도 전처리가 필요하다.</p>
<p>이미지 데이터의 전처리 과정은 상당히 다양한 라이브러리와 함수를 이용해 진행할 수 있다.</p>
<p>가장 중요한 과정들을 개략적으로 살펴보자면,</p>
<ol>
<li>이미지 데이터 읽어오기</li>
<li>이미지 사이즈 조절 및 색상 조절, 스케일링</li>
<li>이미지 증강 및 전처리</li>
<li>데이터셋 만들기</li>
</ol>
<p>로 요약할 수 있을 것 같다.</p>
<p>해당 과정들을 함수로 직접 만들어 진행해보기도 했지만, tf.keras의 기능들을 사용하면 손쉽게 진행할 수도 있었다.
cv2나 PIL을 이용해 이미지를 읽고, 사이즈 및 색상을 조절한 후 
ImageDataGenerator를 통해 이미지 증강 및 데이터셋 만들기 작업을 한 번에 처리할 수 있었다.</p>
<hr>
<h1 id="이미지-읽어오기-및-기본-처리">이미지 읽어오기 및 기본 처리</h1>
<h2 id="matplotlibpyplot">matplotlib.pyplot</h2>
<ul>
<li><p><code>plt.imread()</code>
이미지 파일을 이미지로 읽어온다.</p>
</li>
<li><p><code>plt.imshow()</code>
읽어온 이미지를 출력한다.
이때, 이미지의 구성요소에 대해 기억해보면 [height, width, channel]이었다.
따라서 img[0:0:1]등의 방법으로 1번 인덱스(R) 채널의 이미지만 읽어올 수도 있다.</p>
</li>
</ul>
<h2 id="pil">PIL</h2>
<p>-&gt; from PIL import Image</p>
<ul>
<li><p><code>PIL.Image.open</code>
image 파일을 읽어들인다.</p>
</li>
<li><p><code>.size</code>
이미지 파일의 사이즈를 확인한다.</p>
</li>
<li><p><code>.resize()</code>
이미지 파일의 사이즈를 변경한다.</p>
</li>
<li><p><code>.save()</code>
이미지 파일을 저장한다.</p>
</li>
</ul>
<h2 id="opencv">OpenCV</h2>
<ul>
<li><p><code>img = cv2.imread()</code>
cv2에서 imread로 읽어온 이미지는, PIL에서 읽어온 것과 다르게 array 형태이다.
따라서 이미지를 출력해주기 위해서는 <code>plt.imshow()</code>를 사용한다.
또한, nparray형태이므로, 슬라이싱으로 반만 읽어와서 절반으로 잘린 형태의 이미지를 출력하는 것도 가능하다.</p>
</li>
<li><p><code>cv2.cvtColor(img, cv2.COLOR_BGR2RGB)</code>
OpenCV의 경우, 컬러 채널이 RGB가 아닌 BGR의 형태를 취하고 있다.
따라서 이미지를 RGB 형태로 다뤄주기 위해서는, cvtColor를 통해 cv2.COLOR_BGR2RGB를 적용해주어야 한다.</p>
</li>
<li><p><code>cv2.imread(img, cv2.IMREAD_~~~~)</code>
다양한 옵션을 주면서 이미지를 읽어올 수 있다.
IMREAD_UNCHANGED
IMREAD_GRAYSCALE
등이 존재한다.</p>
</li>
<li><p><code>cv2.resize()</code>
역시 이미지의 사이즈를 조절할 수 있다.</p>
</li>
</ul>
<h2 id="tfkeraslayersrescaling">tf.keras.layers.Rescaling</h2>
<ul>
<li><code>tf.keras.layers.Rescaling</code>
값을 정규화 할 수 있다.</li>
</ul>
<p>다음과 같이 사용한다.</p>
<pre><code class="language-python">normalization_layer = layers.Rescaling(1./255)</code></pre>
<p>이렇게 레이어로 만들어준 후 모델의 입력층에 추가하면 된다.
혹은 map함수를 사용하여 적용할 수도 있다.</p>
<hr>
<h1 id="이미지-증강">이미지 증강</h1>
<h2 id="pil-1">PIL</h2>
<p>-&gt; from PIL import ImageFilter</p>
<ul>
<li><code>img.filter()</code>
이렇게 사용하는데, 그 안에 들어가는 인자가 ImageFilter의 모듈이다.<ul>
<li><code>ImageFilter.BLUR</code> : 흐리게 만든다.</li>
<li><code>ImageFilter.GaussianBlur</code> : 가우시안 필터를 통해 흐리게 만든다. (픽셀의 거리에 따라 가중치를 두어 계산하는 방식)</li>
<li><code>ImageFilter.CONTOUR</code> : 등고선을 추출한다.</li>
<li><code>ImageFilter.EMBOSS</code> : EMBOSS 효과를 적용한다.</li>
</ul>
</li>
</ul>
<h2 id="opencv-1">OpenCV</h2>
<ul>
<li><p><code>cv2.blur()</code>
이미지를 흐리게 만든다.</p>
</li>
<li><p><code>cv2.adaptiveThreshold()</code>
이미지의 임계값을 특정 임계값을 기준으로 크고 작은 값으로 구분하여 이진화한다. 
adaptiveThreshold는 적응적 이진화 이므로, 이 임계값이 주변 픽셀의 강도에 의해 결정된다.</p>
</li>
</ul>
<h2 id="tfkeraslayers">tf.keras.layers</h2>
<ul>
<li><code>layers.RandomFlip()</code>
학습과정에서 이미지를 상하 혹은 좌우 반전시킨다.</li>
<li><code>layers.RandomRotation()</code>
학습 과정에서 랜덤으로 이미지를 선택하여 회전시킨다.</li>
<li><code>layers.RandomZoom()</code>
학습 과정에서 랜덤으로 이미지를 선택하여 확대 혹은 축소한다.</li>
</ul>
<p>-&gt; 해당 레이어들을 모델 내부에 포함시킨 후 학습을 진행하면 이미지 증강의 효과를 얻을 수 있다.</p>
<hr>
<h1 id="파이프라인">파이프라인</h1>
<p>이제는 해당 기능들 혹은 다른 기능들을 한번에 수행할 수 있는 파이프라인 같은 역할을 하는 함수들을 살펴보자.</p>
<h2 id="image_dataset_from_directory">image_dataset_from_directory</h2>
<ul>
<li><code>tf.keras.utils.image_dataset_from_directory</code><a href="https://www.tensorflow.org/api_docs/python/tf/keras/utils/image_dataset_from_directory">링크</a></li>
<li><blockquote>
<p>디렉토리 경로를 주면 해당 디렉토리 안의 이미지 파일들을 dataset 형식으로 만들어준다. image_size를 지정해줄 수도 있고, validation_set을 나누어주는 기능도 제공한다.</p>
</blockquote>
</li>
<li>다만 이미지 증강 기능을 수행할 수 없는 것 같다!</li>
</ul>
<ul>
<li>사용예제<pre><code class="language-python">train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset=&quot;training&quot;,
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
</code></pre>
</li>
</ul>
<p>val_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset=&quot;validation&quot;,
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)</p>
<pre><code>- subset
Subset of the data to return. One of &quot;training&quot;, &quot;validation&quot; or &quot;both&quot;. Only used if validation_split is set. When subset=&quot;both&quot;, the utility returns a tuple of two datasets (the training and validation datasets respectively).

이렇게 나누어진 데이터셋에 `.class_names` 를 통하여 class의 종류를 확인할 수 있다.

음... flow_from_directory 랑 비슷한 역할인 것 같은데?

## ImageDataGenerator
- `from tensorflow.keras.preprocessing.image import ImageDataGenerator`
특정 경로에 있는 이미지들을 데이터셋으로 만들어주는 generator를 생성해준다.

이미지를 데이터셋으로 만들어 주는 것이 아닌, generator를 생성해주는 함수이다! 다양한 이미지 증강을 적용하여 이미지들을 데이터셋으로 만들어주는 generator를 생성한다.

그리고 이거랑 flow_from_directory랑도 많이 헷갈렸는데, ImageDataGenerator로 만든 generator에서, flow_from_directory를 사용해서 데이터셋을 만드는 것이다!

사용예시
```python
# ImageDataGenerator 를 통해 이미지를 로드하고 전처리 합니다.
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# validation_split 값을 통해 학습:검증 비율을 8:2 로 나눕니다.
datagen = ImageDataGenerator(rescale=1/255.0, validation_split=0.2)
datagen</code></pre><p>인자</p>
<ul>
<li>이미지의 조정 및 증강에 관련한 다양한 인자를 넣어줄 수 있다.</li>
<li>rescale</li>
<li>horizontal_flip : 좌우반전</li>
<li>vertical_flip : 상하반전</li>
<li>rotation_range : 회전</li>
<li>zoom_range : 확대 혹은 축소</li>
<li>width_shift_range, height_shift_range : 이동</li>
<li>shear_range : 눕히기</li>
<li>brightness_range(min, max) : 밝기 조절</li>
<li>channel_shift_range : RGB 픽셀 값을 변경</li>
</ul>
<p>-&gt; ImageDataGenerator를 통해 데이터를 만들 때, 해당 인자들을 포함하여 이미지 증강을 수행할 수 있다.</p>
<ul>
<li>validation_split 값을 넣어주어, 이미지 데이터를 생성할때 validation set의 비율을 어느정도로 할지 결정할 수 있다.</li>
</ul>
<h2 id="flow_from_directory">flow_from_directory</h2>
<p>ImageDataGenerator의 메소드로, 이미지를 특정 경로에서 불러와서 numpy array로 만들어주는 함수이다.
Generator에서 해당 메소드를 사용하면 특정 경로에 있는 이미지들을 통해 증강된 데이터들의 batches를 생성한다.</p>
<p>아까 위에서 살펴본 image_dataset_from_directory와 비슷하다.</p>
<p>사용예시</p>
<pre><code class="language-python"># flow_from_directory 를 통해 이미지를 불러옵니다.
# training 데이터셋을 생성합니다.
# class_mode 에는 이진분류이기 때문에 binary 를 넣어줍니다.
trainDatagen = datagen.flow_from_directory(directory = &#39;cell_images/&#39;,
                                           target_size = (height, width),
                                           class_mode = &#39;binary&#39;,
                                           batch_size = 64,
                                           subset=&#39;training&#39;)</code></pre>
<p>포함되는 인자로는 다음이 있다.</p>
<ul>
<li>directory : 이미지파일이 위치하는 경로</li>
<li>target_size : 이미지 파일을 어떤 사이즈로 만들 것인지</li>
<li>class_mode : One of &quot;categorical&quot;, &quot;binary&quot;, &quot;sparse&quot;, &quot;input&quot;, or None. Default: &quot;categorical&quot;.</li>
<li>batch_size : Size of the batches of data (default: 32).</li>
</ul>
<p>이렇게 만든 데이터셋에서는 다음을 확인할 수 있다.</p>
<ul>
<li><code>.num_classes</code></li>
<li><code>.classes</code></li>
<li><code>.class_indices</code></li>
</ul>
<hr>
<h1 id="기타">기타</h1>
<h2 id="os">os</h2>
<ul>
<li><code>os.walk</code>
해당 디렉토리 아래에 있는 디렉토리와 파일들의 이름을 모두 반환하는 generator를 생성한다.</li>
</ul>
<p>사용예제</p>
<pre><code class="language-python">import os
for dirpath, dirnames, filenames in os.walk(&#39;cell_images/&#39;):
    print(dirpath, dirnames)</code></pre>
<ul>
<li><code>os.listdir()</code>
해당 경로에 있는 모든 파일과 폴더명 리스트를 반환한다.</li>
</ul>
<hr>
<p>참고자료</p>
<ul>
<li><a href="https://techblog-history-younghunjo1.tistory.com/261">https://techblog-history-younghunjo1.tistory.com/261</a></li>
<li><a href="https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator#flow_from_directory">https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator#flow_from_directory</a></li>
<li><a href="https://colinch4.github.io/2020-12-04/ImageDataGenerator1/">https://colinch4.github.io/2020-12-04/ImageDataGenerator1/</a></li>
<li><a href="https://yganalyst.github.io/data_handling/memo_1/">https://yganalyst.github.io/data_handling/memo_1/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 52] lightgbm]]></title>
            <link>https://velog.io/@im_ngooh/Day-52-lightgbm</link>
            <guid>https://velog.io/@im_ngooh/Day-52-lightgbm</guid>
            <pubDate>Thu, 24 Nov 2022 08:45:55 GMT</pubDate>
            <description><![CDATA[<h1 id="goss와-efb">GOSS와 EFB</h1>
<p>어제 lightgbm 복습하다 난관에 봉착했던 GOSS와 EFB에 대해서 오늘 으쌰 복습 시간에 공부했다.</p>
<p>특히 GOSS는 발표까지 할뻔했어서 열심히 공부했다! EFB는 좀 더 어렵네...!</p>
<h2 id="gossgradient-based-one-side-sampling">GOSS(Gradient based one side sampling)</h2>
<p>GOSS, gradient based one side sampling은 데이터의 행을 효과적으로 줄이는 방법입니다.</p>
<ul>
<li>의의</li>
</ul>
<p>gradient boosting은 데이터의 행의 개수와 열의 개수가 많으면 시간이 오래걸린다는 문제가 있었습니다. 이러한 문제를 해결하기 위해 데이터의 행의 개수를 줄여주는 방법이 바로 GOSS입니다.
GOSS는 큰 그라디언트를 가진 모든 인스턴스, 즉 행들은 유지하고 작은 그라디언트를 가진 인스턴스들은 무작위로 샘플링을 수행하는 방법을 통해 행의 개수를 줄입니다.</p>
<ul>
<li>아이디어</li>
</ul>
<p>GOSS는 기울기 기반 단측 표본 추출법이라고 할 수 있습니다. 말이 좀 어렵지만,
결국 gradient를 기반으로 어떤 데이터가 학습에 많이 도움이 되는 데이터인지 또 어떤 데이터가 학습에 별로 도움이 되지 않는 데이터인지를 파악하는 것.
그리고 학습에 도움이 되는 데이터 위주로 데이터를 샘플링하여 행의 개수를 줄이는 방법이라고 할 수 있습니다.</p>
<p> <img src="https://velog.velcdn.com/images/im_ngooh/post/71a31294-062c-403c-8550-3e2ee7fbb611/image.png" alt="">
 출처: <a href="https://www.slideshare.net/suman_lim/boostingsuman">https://www.slideshare.net/suman_lim/boostingsuman</a></p>
<p>이 사진이 GOSS를 잘 설명 해주고있는 사진인데, 초록색으로 표시된 데이터들은 gradient가 큰 데이터들이고, 노란색으로 표시된 데이터들은 그라디언트가 작은 데이터들입니다. 따라서 GOSS에서는 초록색 데이터들은 모두 사용하고, 노란색 데이터들은 일부만 샘플링하여 오른쪽과 같은 데이터를 만들었습니다. 이게 바로 GOSS입니다.  그라디언트가 큰 데이터들은 모두, 작은 데이터들은 일부만 샘플링하여 사용함으로써 데이터의 행의 개수를 줄입니다.</p>
<ul>
<li>좀 더 자세한 이해!</li>
</ul>
<p>좀 더 자세하게 살펴보겠습니다.
GOSS는 lightgbm의 대표적인 특징입니다. 그리고 이 lightgbm이라는 모델은 gradient boosting Decision Tree, GBDT를 기반으로 하는 모델입니다. 그러니까 그 말은, gradient boosting을 활용하고 있는 모델이라는 뜻입니다. 즉, 하나의 트리로 예측을 한 후 생긴 잔차들을 경사하강법을 이용해 학습해나가며 boosting을 통해 예측을 진행하는 모델입니다.</p>
<p>따라서, GOSS에서 데이터의 행의 개수를 줄일 때에도 gradient를 참고하여, 덜 훈련된 데이터 위주로 줄여주는 것이 효과적일 것입니다.
만약에 데이터의 gradient가 크다면, 해당 데이터는 loss 함수의 값이 크고, 충분히 훈련되지 못한 인스턴스일 것입니다. 
반면에 gradient가 작다면, 해당 인스턴스는 충분히 훈련되어 loss역시 작은, 학습이 잘 된 인스턴스일 것입니다.
그렇다면 Boositng을 진행하면서 데이터의 행의 개수를 줄일 때, 당연히 덜 훈련된 데이터, 즉 gradient가 큰 데이터 위주로 줄인다면, 더욱 효과적인 학습을 진행할 수 있을 것입니다.</p>
<p>그런데 그렇다고 해서 작은 gradient를 갖는 인스턴스들을 모두 없애버린다면, 데이터 전체의 분포가 달라져 문제가 생길 수 있습니다. 따라서, 그라디언트가 작은 인스턴스들은 랜덤하게 샘플링하여 일부만 사용합니다.
그리고 분기를 위한 계산 같은 때에, 해당 인스턴스들에 가중치를 주는 방식으로 사용하여 분포를 유지하며, 실질적인 데이터의 행의 개수를 줄일 수 있습니다.</p>
<p>잠시 위의 사진으로 돌아가, 오른쪽 데이터를 보면, weights라는게 있습니다. 데이터를 모두 사용한 초록색에 비해, 절반만 사용한 노란색 데이터의 weights가 큰 걸 알 수 있습니다. 이 weights가 바로 분포를 유지하면서 행의 개수를 줄이기 위해 사용하는 가중치라고 생각하시면 될 것 같습니다.</p>
<ul>
<li>알고리즘
<img src="https://velog.velcdn.com/images/im_ngooh/post/81431e0d-cb3f-4bf2-a0b9-9adaddbac909/image.png" alt="">
출처 : <a href="https://proceedings.neurips.cc/paper/2017/file/6449f44a102fde848669bdd9eb6b76fa-Paper.pdf">https://proceedings.neurips.cc/paper/2017/file/6449f44a102fde848669bdd9eb6b76fa-Paper.pdf</a></li>
</ul>
<p>이 알고리즘은, lightgbm 발표 논문에 포함되어 있는 내용입니다. 
GOSS의 알고리즘을 설명해주고 있습니다. </p>
<ol>
<li>각 instance들의 gradient 계산 및 정렬</li>
<li>gradient 상위 a×100% 만큼의 instance 선택</li>
<li>남은 instance들 중에서 b×100% 만큼을 무작위로 선택하고, 이 instance들에 상수 (1−a)/b 을 곱하여 데이터의 전체 개수를 맞춰준다.<ul>
<li>이 instance들은 모델이 이미 충분히 학습한 데이터지만, 데이터셋의 분포를 유지하기 위해 일부분을 포함시킨다.</li>
<li>(1−a)/b는 트리 Split 과정에서 information gain을 계산할 때 가중치를 곱해주는 역할을 한다.</li>
<li>b의 값이 적을수록 큰 가중치를 곱해주게 된다.</li>
<li>이를 통해 원래 데이터셋의 분포를 크게 변화시키지 않고 데이터셋의 크기를 줄일 수 있다.</li>
<li>분기 계산 시 작은 gradient를 가지는 랜덤 샘플링된 데이터들을 여러 번 반복하여 들어있는 형태로 생각하고 가중치를 주어 계산한다. → 분포를 유지</li>
</ul>
</li>
<li>선택한 instance 들로 GBDT 생성</li>
</ol>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/a133c926-5b83-49ad-9771-727aecc94e42/image.png" alt="">
출처 : <a href="http://machinelearningkorea.com/2019/09/25/lightgbm%EC%9D%98-%ED%95%B5%EC%8B%AC%EC%9D%B4%ED%95%B4/">http://machinelearningkorea.com/2019/09/25/lightgbm%EC%9D%98-%ED%95%B5%EC%8B%AC%EC%9D%B4%ED%95%B4/</a>
그래서 다시 한번 요약하자면, 큰 그라디언트를 가진 모든 인스턴스를 유지하고, 작은 그라디언트를 가진 인스턴스를 무작위로 샘플링하는 방법으로 행을 줄이는 것이 바로 GOSS 였습니다.</p>
<h2 id="efbextra-feature-bundling">EFB(Extra Feature bundling)</h2>
<p>어제 공부한바로는, Exclusive한, 즉 동시에 0이 되지 않는 feature들을 하나의 bundle으로 묶어주는 것이 바로 EFB였다.
그리고 이건 히스토그램 기반 그라디언트 부스팅의 특징을 이용한 것이었다.</p>
<ul>
<li>EFB란</li>
</ul>
<p>변수를 줄여 차원을 효과적으로 감소시키는 새로운 방법이 EFB라고 한다.
feature들을 하나로 묶어, 0의 개수가 적은 feature를 생성한다.
이를 통해 트리의 가지를 뻗어나가면서 사용되는 feature의 가짓수를 줄여 트리가 overfitting 되는 것을 방지한다.</p>
<ul>
<li>어떻게?</li>
</ul>
<p>Greedy하게 진행해야한다.
그래프 색칠 알고리즘을 통해 해결한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/625d8e22-94a2-4bca-b828-10b630b1224c/image.png" alt=""></p>
<p>해당 알고리즘에서, 최소한으로 필요한 색깔의 수는 EFB에서 최소로 필요한 bundle 개수이다.
배타적인 features로 이루어진 bundle이 동일한 색상을 가진 vertex의 집합인 것이다.</p>
<p>알고리즘은 다음과 같다.</p>
<ol>
<li>변수들의 상호배타여부를 고려하여 그래프 생성<ul>
<li>데이터셋의 각 변수들을 그래프의 vertex(꼭짓점)로 치환</li>
<li>서로 상호배타적인 변수들은 Edge로 연결되어 있지 않음</li>
<li>각 Edge의 Weight는 Edge와 연결된 두 Vertex 사이의 conflict</li>
</ul>
</li>
<li>그래프의 각 Vertex들의 Degree를 계산하고, Degree의 크기에 따라 정렬<ul>
<li>Vertex의 Degree는 해당 Vertex에 연결된 모든 Edge들의 weight의 합</li>
</ul>
</li>
<li>bundle을 만들고, Degree가 큰 변수 순서대로, 나머지 다른 변수들간의 conflict 계산</li>
<li>conflict의 합이 전체 데이터셋 개수 * r * 100% 미만이 될 때까지 bundle에 추가</li>
<li>bundle의 conflict 합이 기준을 넘어가면 새로운 bundle을 만들고, 모든 변수를 다 쓸 때까지 3, 4과정을 반복</li>
</ol>
<ul>
<li>음? ㅠㅠ</li>
</ul>
<p>그러니까... 저런 방식을 통해 진행한다..
그래프 색칠 알고리즘이라는 방식과 동일하게 진행되면서, 히스토그램 방식을 데이터프레임에 차용하고 있다.
각각의 데이터를 그래프에 존재하는 꼭짓점(vertex)라고 생각하고, 그래프를 그려준다.
해당 그래프에서 상호배타적인(Exclusive)한 데이터들은 서로 연결되어있지 않다.
그 후 그래프에서 degree, 즉 연결된 Edge가 많은 순으로 데이터를 정렬한 후
해당 feature들을 bundle로 만든다.
기존에 존재하는 bundle이 있고 그것과의 conflict(상호배타적이지 않은 instance의 개수) 가 작다면 기존의 번들로 묶고, 그렇지 않다면 새로운 번들로 만든다.</p>
<p>한 번들 내에서 값을 합쳐 하나의 변수로 만드는 것은?</p>
<ol>
<li>bundle 내에서 기준 변수 설정</li>
<li>모든 instance에 대해서, conflict 한 경우는 기준 변수 값 그대로 가져감</li>
<li>모든 instance에 대해서, conflict가 아닌 (상호배타적인) 경우 기준 변수의 최대값 + 다른 변수 값을 취함
<img src="https://velog.velcdn.com/images/im_ngooh/post/d0dc88c3-1782-4850-9acc-b4ea9bc35045/image.png" alt="">
출처 : <a href="https://kicarussays.tistory.com/38">https://kicarussays.tistory.com/38</a></li>
</ol>
<p>만약 한 feature의 분포가 0<del>20이고 한 feautre의 분포가 0</del>30이면 뒤쪽 feature 에다가 10을 더해서 10~40이되도록 만들고 이를 합칠 수 있다. 이렇게 되면 트리모델에서는 feature마다 서로 간섭이 없으며 기존의 충돌이 났던 부분에 있어서도 커버가 가능하다.</p>
<p>feature의 수가 수백만개를 넘어가 너무 많다면 어려움이 있을 수 있다고 한다.</p>
<p>흠.. 조금은 이해가 된다! 복잡하고 어렵긴 하다....</p>
<p>lightgbm은 히스토그램 기반 그라디언트 부스팅 알고리즘인데, 즉 입력 feature를 256개의 bins로 나누어 사용하는 것이다. 이때 bins 중 하나는 떼어놓고 결측치를 처리하기 위해 사용한다.
히스토그램 기반 알고리즘은 연속적인 Feature 값 대신 이산적인 Bins를 저장하기 때문에, bins에 배타적인 Features를 넣어서 Feature Bundle을 구축할 수 있다.
sparse(희소한) feature들을 하나의 bins에 넣어 bundle로 사용함으로써, 각각의 feature가 어디에 있는지 tracking이 가능함과 동시에, sparse하지 않은 하나의 feature로 (번들) 만들 수 있는 것!
feature와 관련된 정보를 유실하지 않고도 효과적으로 feature의 수를 줄일 수 있다</p>
<h2 id="어찌-되었든">어찌 되었든!</h2>
<p>GOSS와 EFB를 통해서, lightgbm은 데이터의 사이즈를 줄여 속도 측면에서 획기적인 발전을 이루어내었다!
GOSS는 그라디언트를 기반으로, 높은 그라디언트는 유지, 낮은 것은 샘플링하여 행을 줄이는 것!
EFB는 그래프 방식을 통해 Exclusive한 feature 들끼리 하나의 bundle로 만들어주어 feature가 특성을 잃지 않으면서도 feature의 개수를 줄여준다. 이는 lightgbm이 히스토그램 기반 작동방식을 사용하고 있기 때문에 가능한 것이다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 45, 46] 피쳐 엔지니어링, 부스팅]]></title>
            <link>https://velog.io/@im_ngooh/Day-45-46-%ED%94%BC%EC%B3%90-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-%EB%B6%80%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@im_ngooh/Day-45-46-%ED%94%BC%EC%B3%90-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4%EB%A7%81-%EB%B6%80%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Wed, 23 Nov 2022 16:34:43 GMT</pubDate>
            <description><![CDATA[<p>11.15 / 11.16
피쳐 엔지니어링과 부스팅에 대해 배웠다.</p>
<hr>
<p>해당 내용은 멋쟁이사자처럼 AI School 오늘코드 박조은 강사님의 자료를 참고하였습니다.</p>
<hr>
<h1 id="feature-engineering">feature engineering</h1>
<p>0702 파일</p>
<h3 id="log-변환">log 변환</h3>
<p>왜도와 첨도 혹은 히스토그램을 통해 데이터의 분포를 파악한 후, 분포가 너무 치우쳐있는 형태라면 해당 feature를 log 변환 해주는게 좋을 수 있다.
분포가 고를 수록 학습과 예측에 도움이 되기 때문!</p>
<h3 id="polynomial-features">polynomial features</h3>
<p>언제 사용했지? uniform 한 데이터여서 특성이 너무 드러나지 않을때, 제곱을 하거나 곱해주는 방식으로 여러 특성을 살펴보고 학습과 예측에 도움이 되기 위해 사용했었다.
sklearn의 polynomialfeatures를 통해서도 구현할 수 있었지만, 이번 실습에서는 직접 제곱을 해주는 방법으로도 구현해보았다.
아주 다양한 방법이 있구나...! 정답은 없고...! 상황에 맞춰 마음대로 잘 선택해가면 되겠다...</p>
<p>어쨌든 값을 강조해서 구분해서 보고자 할 때, 분포의 특성이 더 잘 드러나도록 보고 싶을 때, polynomial features를 사용하거나, 그냥 피쳐에 제곱을 해주어 분포를 더 강조하여 볼 수 있다는 것!! 알아두자….!</p>
<h3 id="이상치-처리">이상치 처리</h3>
<p>이상치란 너무 크거나 작아 범위를 벗어나는 값으로, 주로 제거 혹은 대체한다.
오류값이란 데이터의 수집 및 입력 과정에서 잘못 입력된 값으로, 역시 주로 제거 혹은 대체한다.</p>
<h3 id="이산화">이산화</h3>
<p>binning이라고도 부르며, pd.cut과 pd.qcut을 통해 equal width 또는 equal frequency binning을 할 수 있다.</p>
<h3 id="결측치-처리-imputation결측치-대체">결측치 처리, imputation(결측치 대체)</h3>
<p>결측치가 많은 feature라고 해서 무조건 삭제하는게 나은 방법이라는 보장은 없다. 오히려 그것이 중요한 신호일 수 있다! 
범주형 변수의 경우 결측치가 있더라도 인코딩할때 저절로 0으로 처리될 것이고,
수치형 변수의 경우 결측치를 잘못 채우게 되면 오해가 생길 수 있으니 주의가 필요하다! 원래의 값을 너무 왜곡시키면 안된다! 회귀와 같은 머신러닝 알고리즘으로 채울 수도 있고, 보간법을 사용하거나 대표값을 이용해 채울 수도 있고, 기준을 잡아 기준에 따라 다른 값으로 채워줄 수도 있다!</p>
<p>결측치를 어떻게 처리해야할지에 대한 판단은, 차차 배워나가고, 여러 노트북을 필사해보며 기준을 스스로 익히고 판단하여 선택하면 된다. 연습이 필요하다!</p>
<h3 id="scaling">scaling</h3>
<p>지금은 tree 기반의 모델을 사용하고 있기 때문에 scaling을 하고 있지 않지만, 만약 다른 모델들을 사용한다면 꼭!!! standardscaler, minmaxscaler, robustScaler 등을 이용해 scaling 해주어야 한다.</p>
<h3 id="train---test-나누기">train - test 나누기</h3>
<p>이번 실습에서는, 전처리를 한번에 해주기 위해 train과 test를 합친 후 진행했었다. 전처리 완료 후 다시 train 과 test를 나눠줬어야 하는데, 어떻게 하면 될까?
전처리 과정에서 행을 삭제한게 없다면, 합쳐주기 전 train set의 행의 개수를 이용해 iloc으로 슬라이싱하여 나눠주면 될 것이다!</p>
<p>-&gt; 수치형과 범주형 변수에서 전처리할 수 있는 방법이 다르기 때문에 EDA과정에서 데이터를 꼼꼼히 탐색하는 것이 중요하다!</p>
<h1 id="kfold">KFold</h1>
<p>KFold는 주어진 데이터셋을 여러 개의 Fold로 분할해준다.</p>
<pre><code class="language-python">from sklearn.model_selection import KFold

kf = KFold(n_splits = 5, shuffle = True, random_state = 42)
kf</code></pre>
<p>이렇게 만들어줄 수 있다.
굳이 KFold를 사용하는 이유는, shuffle 인자를 이용해 데이터셋의 순서를 섞은 후 fold를 나눌 수 있으며, random_state를 지정하여 분할이 바뀌지 않도록 해줄 수 있기 때문이다!
따라서 이를 사용하면 점수의 변화가 분할의 변화 때문인지, 모델의 변화 때문인지를 확실하게 알 수 있다.</p>
<p>이렇게 만든 kfold를 cross_validation에는 이렇게 사용할 수 있다.</p>
<pre><code class="language-python">from sklearn.model_selection import cross_val_predict
y_valid_predict = cross_val_predict(model, X_train, y_train, cv = kf, n_jobs = 10)
y_valid_predict

from sklearn.model_selection import cross_val_score
cross_val_score(model, X_train, y_train, cv = kf, scoring = &#39;neg_root_mean_squared_error&#39;, n_jobs = -1)</code></pre>
<p>사실 약간 왜 쓰는지 이해가 안된다! 
shuffle한 후에 fold를 나누려고 쓴다면 이해가 되겠지만, randomstate를 통해 분할이 바뀌지 않도록 해주어 분할의 변화가 점수에 영향을 미치지 못하게 하기 위해서라는게 이해가 안된다.
그냥 cross_validate를 할때에도, 분할이 바뀌진 않을 것 같은데? 여러번 시행해봐도 같은 결과가 나오기도 하고.. 순서대로 개수에 맞춰 분할되는 거 아닐까?</p>
<p>그래서 kfold를 shuffle = false, n_splits = 5로 하고 
cross_val_score를 cv = kf로 한 후 실행해보았고, cv = 5로 바꿔서도 실행해보았다.
똑같이 나온다! 여러번 실행해도! 똑같다!</p>
<p>그냥 일단은 shuffle 해줄 수도 있고, 미리 나누어놓고 변수에 저장한 후 CV를 할때에는 따로 나눠주는 연산을 하지 않기 위해 사용한다! 라고 이해해야겠다.</p>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html">KFold</a>
The first <code>n_samples % n_splits</code> folds have size <code>n_samples // n_splits + 1</code>, other folds have size <code>n_samples // n_splits</code>, where n_samples is the number of samples. 라고 한다.</p>
<p>cross_val_score의 user guide에 보면, 
The following example demonstrates how to estimate the accuracy of a linear kernel support vector machine on the iris dataset by splitting the data, fitting a model and computing the score 5 consecutive times (with different splits each time):
라고 나와있는데... 내가 해석을 못하는건가... with different splits each time이면 실행할때마다 결과가 달라져야하는거 아닌가..?</p>
<p>근데 cv parameter에 대한 <a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html#sklearn.model_selection.cross_val_score">설명</a>을 보면 이렇게도 나와있다!
For int/None inputs, if the estimator is a classifier and y is either binary or multiclass, StratifiedKFold is used. In all other cases, KFold is used. These splitters are instantiated with <code>shuffle=False</code> so the splits will be the same across calls.
그럼 똑같이 나오는게 맞다!</p>
<p>그러면 위에서 쓴 대로! shuffle 해줄 수도 있고, 미리 나누어놓고 변수에 저장한 후 CV를 할때에는 따로 나눠주는 연산을 하지 않기 위해 사용한다! 라고 이해하자.</p>
<hr>
<h1 id="linear-regression">Linear Regression</h1>
<p>실습 파일 0801로 넘어옴!
<a href="https://www.kaggle.com/c/mercedes-benz-greener-manufacturing">Kaggle Benz dataset</a>(제조업, 센서데이터)로 실습</p>
<h2 id="eda">EDA</h2>
<p>데이터셋의 특이한 점을 보면, 다 익명화되어있다. 이렇게!
<img src="https://velog.velcdn.com/images/im_ngooh/post/263099ff-fb71-4e4c-9014-2f6d40bc0bbb/image.png" alt="">
보안을 위해 익명 처리 해주었다고 한다.</p>
<ul>
<li>feature가 800여개 존재한다. 피쳐 엔지니어링에 도전해볼 데이터셋이다.</li>
<li>그 중 nunique가 1인 변수들이 있다. 이러한 변수들은 예측에 크게 도움이 되지 않을 듯 하므로, 제거해준다.<pre><code class="language-python">train_nunique = train.nunique().sort_values()
train_one_idx =train_nunique[train_nunique == 1].index
train = train.drop(columns = train_one_idx)
</code></pre>
</li>
</ul>
<p>test = test.drop(columns = train_one_idx)</p>
<pre><code>test에도 전처리 해주는거 잊지 말고, 해줄 때 train data 기준으로 해주는거 헷갈리지 말고!

- heatmap을 꼭 corr()를 시각화할때만 사용하지 않는다. 옛날에 미드프로젝트에서 나도 그냥 피벗테이블 시각화를 heatmap으로 한 적 있었듯이, 다양하게 활용할 수 있다.
여기서는 전체 변수들의 분포를 확인해보고자 전체 수치형변수들을 heatmap으로 그렸다.

-&gt; describe에서도 알 수 있긴 하지만, 모든 값들이 다 0~1 사이에 존재하는 값임을 알 수 있다.

### One Hot Encoding
이 날 배운 내용 중 가장 새로웠던 내용 중 하나.
sklearn의 OneHotEncoder를 제대로 사용해보았다.

전에 사용했던 것, 정리했던 것과 사용법은 동일하다.
handle_unknown = &#39;ignore&#39;를 통해서 test에만 있는 범주의 경우 결측치 처리하도록 해주는 것이 필요했었다. ode를 사용한다면 &#39;use_encoded_value&#39;로 사용한다.
여기서 배운 중요한 건, pd.get_dummies()와 달리 OneHotEncoder()는 범주형 변수만 스스로 골라 인코딩을 해주는 것이 아니라, **수치형 변수까지 모두 인코딩해준다**는 것!
이걸 명심하고, 범주형만 인코딩하고 다시 붙이던가 하는 방식으로 사용해야 한다.

또한, OneHotEncoder와 같은 sklearn.preprocessing의 일부 모듈들은 transform 한 결과물로써 데이터프레임이 아닌, matrix를 반환하였었다.
따라서 get_feature_names_out()을 통해 피쳐의 이름과 합쳐 데이터프레임을 만들었어야 했다. 그런데 이때, 만약 원 데이터프레임의 index가 지정되어있었다면, 그러니까 그냥 0 1 2 등 값이 아니라, 하나의 컬럼을 index로 만들어놓은 상태였다면, DataFrame으로 만들때 index도 지정해줘야함을 잊지 말자!

사실 그냥 저 numpy array 상태로 머신러닝 모델들에 줘도 된다. 근데 나는 내가 보기에 데이터프레임이 더 좋은 것 같다.

수치형 변수들로 이루어진 데이터프레임과, 범주형 변수들의 인코딩 결과 데이터프레임을 합칠 때 index가 맞지 않아 오류가 났었었다. 오늘(11.23)도 그랬었고! 까먹지 말자.

```python
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(handle_unknown=&#39;ignore&#39;)

train_ohe = ohe.fit_transform(train.select_dtypes(exclude = &#39;number&#39;)).toarray()
test_ohe = ohe.transform(test.select_dtypes(exclude = &#39;number&#39;)).toarray()

print(train_ohe.shape, test_ohe.shape)
df_train_ohe = pd.DataFrame(train_ohe, columns = ohe.get_feature_names_out(), index= train.index)
df_test_ohe = pd.DataFrame(test_ohe, columns = ohe.get_feature_names_out(), index= test.index)
display(df_train_ohe)
df_test_ohe

df_train = pd.concat([train.select_dtypes(include= &#39;number&#39;),df_train_ohe], axis = 1)
df_test = pd.concat([test.select_dtypes(include= &#39;number&#39;),df_test_ohe], axis = 1)

display(train.shape, df_train.shape, test.shape, df_test.shape)
display(df_train.head())
df_test.head()</code></pre><p>그리고, drop이라는 parameter도 있는데, 만약 이 값을 if_binary 로 설정해주면, 이진형 변수에 대해 하나의 피쳐만 만들어주고, 나머지 하나는 버린다. 그래도 의미는 유지되니까!
그리고 만약에 first로 설정해주면, 모든 피쳐의 첫번째 고유값 피쳐를 버린다. 역시 결측치를 제외하면 의미는 유지될 수 있을테니!</p>
<h2 id="hold-out-validation">hold-out validation</h2>
<p>Cross-validation을 그동안 많이 사용했는데, 시간이 너무 오래걸리기도 하고, hold out validation을 많이들 사용한다고 한다.
train_test_split을 통해 train set과 valid set을 나누어 Hold_out validaion을 진행할 수 있다.</p>
<h2 id="linear-regression-1">Linear Regression</h2>
<p>Linear Regression에 대해 배웠다.</p>
<p>수업들으면서 그럼 DecisionTree Regressor같은건 선형회귀가 아닌건가? 선형 회귀 식을 만드는게 아닌가? 라는 의문이 들었었는데... 이제는 알고 있다!
KMOOC 들으면서 Decision Tree 와 랜덤포레스트 회귀의 원리를 알았으니까!
선형회귀와는 다른 메커니즘이라는 것을 이해했다.</p>
<p><a href="https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%ED%9A%8C%EA%B7%80">위키백과 - 선형회귀</a></p>
<ul>
<li>Linear regression은 종속변수 y와 한 개 이상의 독립변수 X의 선형상관관계를 모델링하는 회귀분석 기법이다.</li>
<li>둘 이상의 설명변수에 기반하는 경우 다중 선형회귀라고 한다.</li>
<li>만약 여러개의 설명변수가 X, X^2, X^3 등이라면 꼭 직선은 아닐수도 있다. X^2 라는 것을 그냥 하나의 변수 X2라고 보면, X2에 대해 선형인 것이므로! 지난번에 얼핏 배운 kernel이 생각난다!</li>
<li>그래도 선형 회귀는 결국 선을 만드는 알고리즘. 기울기(계수)와 절편을 예측하는 것! 선형 모델을 예측한다!</li>
<li><a href="https://ko.wikipedia.org/wiki/%EC%B5%9C%EC%86%8C%EC%A0%9C%EA%B3%B1%EB%B2%95">최소자승법(least square)</a>(RSS(Residual sum of squares)가 최소가 되도록 하는법)을 통해 주로 회귀 모델을 예측한다. 손실 함수(loss function)을 최소화하는 방식으로 세우기도 한다.</li>
</ul>
<p>특징</p>
<ul>
<li>간단하고 빠르다! 이해하기 쉽다.</li>
<li>조정해줄 파라미터가 적다.</li>
<li>이상치의 영향이 크며, 스케일링의 영향을 좀 받는다! 회귀모델은 모두 이상치에 민감하다!!!!</li>
<li>데이터 전처리가 많이 필요하다.</li>
<li>데이터의 수치형 변수가 이루어져 있을 경우나 경향성이 뚜렷할 경우 사용하기 좋다. </li>
<li>Ridge, Lasso, ElasticNet과 같은 선형 회귀 모델의 단점을 보완한 모델들도 있다.</li>
</ul>
<h2 id="sklearn에서">sklearn에서</h2>
<pre><code class="language-python">from sklearn.linear_model import LinearRegression

model = LinearRegression(n_jobs = -1)
model</code></pre>
<p>간단하게 사용할 수 있다!
<a href="https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression">공식문서</a></p>
<p>fit_intercept 를 통해 절편을 사용할건지 안할건지 결정할 수 있다.</p>
<p>예측하고 난 후에, 실제 값과 valid로 예측한 값을 scatterplot으로 그려 예측의 결과를 살펴보는 것도 좋은 아이디어이다!</p>
<hr>
<h1 id="결정-트리-모델과-앙상블">결정 트리 모델과 앙상블</h1>
<p>최근에 자주 보고 있다! 바로 어제 공부했던 내용</p>
<h2 id="결정트리모델">결정트리모델</h2>
<p><a href="https://ko.wikipedia.org/wiki/%EA%B2%B0%EC%A0%95_%ED%8A%B8%EB%A6%AC_%ED%95%99%EC%8A%B5%EB%B2%95">결정트리모델</a></p>
<p>어제 KMOOC 들어보니 CART 알고리즘이라는 것이 결정트리를 구성하는 알고리즘의 종류 중 하나였다. gini 계수를 이용하는!</p>
<p>결정트리 모델은</p>
<ul>
<li>만들어진 모델에 대해서 시각화가 가능하다.</li>
<li>시각화가 가능하므로 비전문가도 이해하기 쉽다.</li>
<li>데이터의 스케일에 구애받지 않는다. (각 특성이 개별적으로 처리됨)</li>
<li>데이터의 내 변수의 종류가 달라도 잘 작동한다. (선형회귀에서는 수치형 변수만 사용 가능했음)</li>
<li>학습용 데이터에 과대적합되는 단점이 있다.</li>
<li>그래도 이상치는 처리 해주는게 좋다! 스케일링은 안해도!</li>
</ul>
<p>어제 배운 바로는, 트리에서 회귀는 해당 노드에 속하는 학습 데이터들의 label의 평균값으로 예측한다고 하였다.</p>
<h2 id="앙상블-기법">앙상블 기법</h2>
<p>앙상블기법을 통해 결정트리 모델의 단점을 보완한다.</p>
<ul>
<li>앙상블 기법이란?
여러 머신러닝 모델을 연결하여 더 강력한 모델을 만드는 기법
앙상블 기법을 이용한 머신러닝 모델은 대표적으로 랜덤포레스트와 그래디언트 부스팅 두 가지가 있다.
둘은 각각 bagging, boosting 의 앙상블을 이용한다.</li>
</ul>
<p>bagging은 부트스트랩을 통해 조금씩 다른 훈련데이터에 대해 훈련된 기초 분류기들을 결합시키는 방법이었고, 편향은 유지하면서 분산은 감소시키기 때문에 포레스트의 성능을 향상시켰다.
따라서 이는 과대적합이 있는 경우 사용하기 적합했다.</p>
<p>랜덤포레스트가 bagging을 활용한 대표적인 예였고</p>
<ul>
<li><p>성능이 뛰어나고 매개변수 튜닝을 많이 필요로 하지 않는다.</p>
</li>
<li><p>결정 트리와 달리 시각화가 불가능하고 비전문가가 이해하기 어려울 수 있다.</p>
</li>
<li><p>데이터의 크기가 커지면 다소 시간이 걸릴 수 있다.</p>
</li>
<li><p>랜덤성이 있기 때문에 random_state 변수를 지정하지 않으면 매번 결과가 달라질 수 있다.</p>
</li>
<li><p>차원이 높고(high-dimensional) 희소한(sparse) 데이터에는 잘 작동하지 않을 수 있다.
라는 특징이 있었다.</p>
</li>
<li><p>Extratree 모델
Extremely Randomized Tree(극도로 무작위화된 모델)이다.
어제 공부했던 내용이 맞다! each tree를 build하는데 whole dataset이 사용되고, 각각의 트리는 최선의 분할이 아닌 랜덤의 분할로 나누어지는 것!
편향은 조금 늘어나지만, 분산을 더 줄일 수 있다!
분할이 랜덤이기 때문에 더 빠르다! 따라서 많은 특성을 고려할 수 있다!
일반적으로 randomforest보다 성능이 조금 더 좋다!</p>
</li>
</ul>
<pre><code class="language-python">from sklearn.ensemble import ExtraTreesRegressor
model_et = ExtraTreesRegressor(random_state=42, n_jobs = 10, n_estimators=400, max_depth = 13)
model_et

model_et.fit(X_train,y_train).predict(X_test)</code></pre>
<h2 id="boosting">boosting</h2>
<p>bagging은 그동안 충분히 다뤘고, 오늘은 boosting에 대해서 공부하면서 정리해보자!!</p>
<p>boosting이란, 여러 얕은 트리를 연결하며 편향과 분산을 줄여 강력한 트리를 생성하는 기법.
이전 트리에서 틀렸던 부분에 가중치를 주며 지속적으로 학습해나간다.
앞의 모델들을 보완해 나가면서 일련의 모델들을 학습시켜 나가는 것이라고 생각하면 된다.</p>
<p>Bagging : parallel, 동시에 학습, 데이터 셋 모델마다 독립적
Boosting : sequential, 순차적 학습, 앞 모델이 데이터 셋 정해줌</p>
<ul>
<li>Gradient descent
<a href="https://en.wikipedia.org/wiki/Gradient_descent">경사하강법 - 위키</a></li>
</ul>
<p>단순히 생각하면, 손실함수 그래프에서 값이 가장 낮은 지점으로 경사를 타고 하강하며 찾아가는 방법.
<img src="https://velog.velcdn.com/images/im_ngooh/post/90e37a2b-fe40-4b45-b542-20f47b656dc8/image.png" alt=""></p>
<p>어제 이미 공부하고 정리 했었기에 자세한 정리는 패스!
다만 중요한 learning rate에 대해서는 다시 잡고 가자.
너무 작으면 시간이 오래걸리고, 너무 크면 아예 도달을 못할 수 있다는 것!
<img src="https://velog.velcdn.com/images/im_ngooh/post/6f7c0445-79b4-425f-aedd-59870f5cc2b1/image.png" alt=""></p>
<h3 id="gbt">GBT</h3>
<p>회귀 또는 분류 분석을 수행할 수 있는, gradient descent를 boosting에 사용한 tree 모델
계산량이 상당히 많이 필요한 알고리즘이기 때문에, 이를 하드웨어 효율적으로 구현하는 것이 필요하다!</p>
<p>강의자료에 있는 그림으로 이해해보자면, </p>
<p>첫번째 트리로 먼저 예측을 진행하고, 그럼 잔차들이 생길것이다.
그럼 그 잔차들 자체를 두번째 트리로 예측을 진행한다. 거기에서 생긴 잔차들에 대해서 또
세번째 트리로 예측을 진행한다.
그렇게 잔차에 대해서 예측을 진행해나가며 잔차를 줄이고, 각각의 트리(weak learner)들을 결합하여 강한 분류기(strong learner)를 만든다. 이게 gradien boosting tree의 원리라고 한다.</p>
<p>GBT의 특징</p>
<ul>
<li>랜덤 포레스트와 다르게 무작위성이 없다.</li>
<li>매개변수를 잘 조정해야 하고 훈련 시간이 길다.</li>
<li>데이터의 스케일에 구애받지 않는다.</li>
<li>고차원의 희소한 데이터에 잘 작동하지 않는다.</li>
</ul>
<p>어찌되었든 트리기반이므로 파라미터가 비슷비슷하다. 특별한 파라미터로는
epoch == n_estimators 와 같은 개념, 학습 횟수를 의미한다. 부스팅 트리에서 n_estimators 는 몇 번째 트리인지를 의미한다.
validation_fraction을 통해 validation 비율을 정할 수 잇고, 이 validation을 통헤 loss를 구하게 된다.
loss = 최적화에 사용할 loss function을 설정한다.
&#39;squared_error&#39;,&#39;absolute_error&#39;,&#39;huber&#39;,&#39;quantile&#39;이 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/e87e973b-b50e-4278-9fef-6765f20de379/image.png" alt=""></p>
<p>squared_error를 가장 많이 사용한다고 한다.
absolute는 미분한 기울기 값이 크기가 방향에 따라 일정하기 때문에 별로 사용하지 않는다. 그리고 미분 불가능하잖아!
Huber는 square와 absolute를 결합한것이고, quatile은 4분위수를 이용하였다. 따라서 이 두개의 값은 이상치에 강건하다.</p>
<p>사실 이 loss 함수들과, loss 함수들을 어떻게 사용하여 최적화를 한다는 것인지 명확하게 이해가 되지는 않았다. 아마 각 트리마다 저 loss 함수들을 이용해서 잔차를 알아내고, 그 잔차에 대해 다음 트리를 통해 예측을 진행하고, 그런 식으로 이루어지는 것 같긴 하다. 그래도 더 공부해봐야한다. 좀 일찍 일찍 좀 공부하자! In each stage a regression tree is fit on the negative gradient of the given loss function. 이라고 나와있긴 하다.</p>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html">Gradient boosting Regressor</a></p>
<pre><code class="language-python">from sklearn.ensemble import GradientBoostingRegressor
model_gbt = GradientBoostingRegressor(random_state=42)
model_gbt

model_gbt.fit(X_train, y_train).predict(X_test)</code></pre>
<p>모델 선언 및 사용에는 여태까지 했던 방식과 크게 다를 것 없다.</p>
<hr>
<p>이제는 사이킷런이 아닌 다른 패키지에서 사용하는 모델들에 대해 배웠다.
xgboost, lightgbm, catboost가 그것이다! 어려웠으니 정신 똑바로 차리자!</p>
<p>해당 모델들은 GBT에서 단점을 보완해 만들어진 것이다.
상황에 따라 적절한 모델을 사용하는 것이 중요하다!</p>
<h1 id="xgboost">xgboost</h1>
<ul>
<li>GBT에서 GPU를 이용한 병렬학습을 지원하여 학습 속도가 빨라진 모델</li>
<li>정규화 그래디언트 부스팅을 제공한다.</li>
<li>기존 GBT에 비해 더 효율적이고, 다양한 종류의 데이터에 대응할 수 있다.</li>
<li>Extreme gradient boosting의 약자이다.</li>
<li>2차 근사식을 바탕으로 한 손실 함수를 토대로, 매 iteration마다 하나의 leaf로부터 가지를 늘려나간다.</li>
<li>손실함수가 최대한 감소하도록 하는 split point(분할점)을 찾는 것이 xgboost의 목표이다.</li>
</ul>
<p>장점</p>
<ul>
<li>GBM 대비 빠른 수행시간(GPU를 이용한 병렬 연산)</li>
<li>과적합 규제! 오버피팅 방지를 위해 regularization이 존재한다.</li>
<li>분류와 회귀 영역에서 뛰어난 예측 성능을 발휘한다.</li>
<li>early stopping 기능이 있다.</li>
<li>다양한 hyper parameter가 존재한다.</li>
</ul>
<p>단점</p>
<ul>
<li>여전히 느리다.</li>
</ul>
<p>특징</p>
<ul>
<li>하이퍼파라미터의 종류가 아주 다양하다.</li>
<li>scikit learn 스타일 api도 제공하고 있어 쉽게 사용할 수 있다.
<a href="https://xgboost.readthedocs.io/en/stable/python/python_api.html#module-xgboost.sklearn">xgboost scikit-learn api</a></li>
</ul>
<p>특히 learning_rate, n_estimators, max_depth, min_child_weight, gamma 등! 이건 오늘자 복습에서 다루자.</p>
<h1 id="lightgbm">lightgbm</h1>
<ul>
<li>결정 트리 알고리즘을 기반으로 하는 분산 그래디언트 부스팅 프레임워크를 제공</li>
<li>성능과 확장성에 초점을 맞추어 개발되었다.</li>
<li>GOSS(Gradient based one side sampling)과 EFB(Exclusive Feature Bundling)을 적용하여 정확도는 유지하며 학습 시간을 상당히 단축시켰다.</li>
</ul>
<p>GOSS와 EFB?
뭔지 진짜 하나도 모르겠다.</p>
<p>장점</p>
<ul>
<li>더 빠른 훈련 속도와 더 높은 효율성</li>
<li>적은 메모리 사용량, 나은 정확도</li>
<li>대규모 데이터의 처리</li>
</ul>
<p>단점</p>
<ul>
<li>overfitting에 민감하고, 작은 데이터에 대해서 과적합되기 쉽다!</li>
</ul>
<p>특징</p>
<ul>
<li>트리 기반이다. 다양한 알고리즘을 지원한다.</li>
<li>leaf-wise 리프 중심 트리 분할 방식을 사용하여, 균형잡힌 트리를 생성하는 것이 아니라 균형을 맞추지 않고 최대 손실 값을 가지는 리프 노드만 지속적으로 분할한다. 이를 통해 비대칭적인 트리 구조를 생성하여 예측 오류 손실을 최소화한다.</li>
<li>GOSS</li>
<li>EFB</li>
</ul>
<p>원래 GBT의 경우, feature의 차원이 높고 데이터의 크기가 클 경우, 가능한 모든 분할 지점의 information gain을 추정하기 위해 모든 데이터 샘플을 탐색해야해 시간이 오래걸렸다.
이러한 문제를 해결하기 위해, lightgbm에서는 feature의 차원을 줄여주고(EFB) 데이터의 크기를 줄여준다(GOSS)</p>
<p>GOSS
Gradeint based one side sampling
데이터에서 큰 gradient를 가진 모든 인스턴스를 사용해서 무작위로 samping을 수행한다.
-&gt; gradient가 크다는 것은, loss가 크다는 것!(많이 틀렸다는 것)
-&gt; sampling을 진행하여 다뤄야할 행, 데이터의 크기를 줄이되, gradient boosting의 컨셉에 맞게 많이 틀린 데이터(gradient가 큰 데이터)들을 위주로 샘플링하여 행을 줄인다!</p>
<p>EFB
Exclusive feature bundling
feature의 개수가 너무 많은 경우 사용하는 것으로, 희소한 행렬에 대해 feature를 하나로 합쳐주는 방법으로 feature의 개수를 줄여준다.
규호님 : Features의 수를 줄이기 위해서 차별화시켜줘서 features를 줄여준 것 입니다!! feature1은 그대로 가져가고 feature2도 그대로 가져가면 feature를 합치는 과정에서 의미가 겹치기 때문에 feature2를 합쳐줄 때 아에 다른 의미를 가진 숫자를 부여해줘서 의미가 안 겹치게 합쳐준 것입니다. 이해가 갈랑말랑 한다.</p>
<h1 id="catboost">catboost</h1>
<ul>
<li>범주형 기능에 대한 기본 처리가 가능하고, 빠른 GPU 훈련을 제공하는 그래디언트 부스틍 프레임워크를 제공</li>
</ul>
<hr>
<h1 id="기타">기타</h1>
<ul>
<li><p>list에 extend로 요소 추가하기
list에 append(list)를 해주면 list 자체가 요소로 추가되지만, extend(list)해주면 해당 list의 요소들이 각각 요소로 추가된다! 까먹지 말자!!!!</p>
</li>
<li><p>ETL과 ELT
<a href="https://www.itworld.co.kr/news/160710">https://www.itworld.co.kr/news/160710</a>
<a href="https://blog.naver.com/freepsw/222276087707">https://blog.naver.com/freepsw/222276087707</a></p>
</li>
<li><p>데이터 불러오기
압축파일(zip)안에 하나의 csv 파일만 담겨있는 경우, 해당 압축파일을 통해 csv를 읽을 수 있다. 이렇게!</p>
<pre><code class="language-python">base_path = &quot;data/benz&quot;
train = pd.read_csv(f&#39;{base_path}/train.csv.zip&#39;, index_col=&quot;ID&quot;)</code></pre>
</li>
<li><p>단기간내에 많은 양을 공부하고 있기 때문이겠지? 공부하다가 보면 전에 한 내용 까먹어있고, 또 하다보면 안하고있는 내용 까먹고.. 꾸준히 실습을 통한 복습을 해줘야겠다..!</p>
</li>
</ul>
<hr>
<h1 id="더-공부해볼-것">더 공부해볼 것</h1>
<ul>
<li>GBT loss 함수 huber loss와 quantile loss</li>
<li>부스팅 3대장 더 공부. 공식문서도 보기.</li>
<li>어제 복습</li>
<li>히스토그램 기반 부스팅 모델? xgboost와 lightgbm이 히스토그램 기반 그래디언트 부스팅이라는 것 같은데..?</li>
<li>예습 과제</li>
<li>gradient, divergence, curl</li>
<li>Ridge, Lasso, ElasticNet 등 선형 회귀 보완 모델</li>
</ul>
<hr>
<p>참고자료
<a href="https://wikidocs.net/21670">https://wikidocs.net/21670</a>
<a href="https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%ED%9A%8C%EA%B7%80">https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%ED%9A%8C%EA%B7%80</a>
<a href="https://ko.wikipedia.org/wiki/%EA%B2%B0%EC%A0%95_%ED%8A%B8%EB%A6%AC_%ED%95%99%EC%8A%B5%EB%B2%95">https://ko.wikipedia.org/wiki/%EA%B2%B0%EC%A0%95_%ED%8A%B8%EB%A6%AC_%ED%95%99%EC%8A%B5%EB%B2%95</a>
<a href="https://ko.wikipedia.org/wiki/%EA%B2%BD%EC%82%AC_%ED%95%98%EA%B0%95%EB%B2%95#:~:text=%EA%B2%BD%EC%82%AC%20%ED%95%98%EA%B0%95%EB%B2%95(%E5%82%BE%E6%96%9C%E4%B8%8B%E9%99%8D,%EB%95%8C%EA%B9%8C%EC%A7%80%20%EB%B0%98%EB%B3%B5%EC%8B%9C%ED%82%A4%EB%8A%94%20%EA%B2%83%EC%9D%B4%EB%8B%A4.">https://ko.wikipedia.org/wiki/%EA%B2%BD%EC%82%AC_%ED%95%98%EA%B0%95%EB%B2%95#:~:text=%EA%B2%BD%EC%82%AC%20%ED%95%98%EA%B0%95%EB%B2%95(%E5%82%BE%E6%96%9C%E4%B8%8B%E9%99%8D,%EB%95%8C%EA%B9%8C%EC%A7%80%20%EB%B0%98%EB%B3%B5%EC%8B%9C%ED%82%A4%EB%8A%94%20%EA%B2%83%EC%9D%B4%EB%8B%A4.</a>
<a href="https://en.wikipedia.org/wiki/Gradient_descent">https://en.wikipedia.org/wiki/Gradient_descent</a>
<a href="https://angeloyeo.github.io/2020/08/16/gradient_descent.html">https://angeloyeo.github.io/2020/08/16/gradient_descent.html</a>
<a href="https://soobarkbar.tistory.com/33">https://soobarkbar.tistory.com/33</a>
<a href="http://hejunhao.me/archives/2023">http://hejunhao.me/archives/2023</a></p>
<hr>
<p>일단 지난주 복습은 여기까지 하고. 내일 오늘거 복습하면서 좀 더 자세히 공부해보자 부스팅계열 모델들은...! 어렵네 어려워. 파이팅!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 50] SVM]]></title>
            <link>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%ED%9B%84-SVM</link>
            <guid>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%ED%9B%84-SVM</guid>
            <pubDate>Tue, 22 Nov 2022 08:42:10 GMT</pubDate>
            <description><![CDATA[<p>11.22. 오후 
<a href="http://www.kmooc.kr/courses/course-v1:SSUk+SSMOOC20K+2022_T1/course/">KMOOC</a> 강의 중 SVM 부분을 수강하고 공부하였다.</p>
<hr>
<h1 id="svm">SVM</h1>
<ul>
<li>최적의 결정 경계(Decision Boundary), 즉 데이터를 분류하는 기준 선을 정의하는 모델</li>
<li>관측치들을 가장 잘 구분해주는 hyperplane 혹은 vector, 분류함수를 찾아내는 것</li>
<li>결정 경계와 Support Vector 사이의 거리 margin이 최대화되는 결정경계를 찾는 기법</li>
<li>Support Vector란, 결정경계와 가장 가까이 있는 데이터 포인트들을 의미한다.</li>
<li>SVM은 수리적 최적화 모형으로 모델링되며 해당 문제를 해결해서 최종 모델을 결정한다.</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>선형이나 비선형 분류, 회귀, 이상치 탐색에도 사용할 수 있는 머신러닝 방법론이다.</li>
<li>딥러닝 이전 시대까지 널리 사용되었다.</li>
<li>고차원의 복잡한 분류 문제를 잘 해결할 수 있다.</li>
<li>상대적으로 작거나 중간 크기를 가진 데이터에 적합하다.</li>
<li>딥러닝보다 앙상블, SVM등이 더 좋은 성능을 보이는 분야들도 존재한다.</li>
<li>margin 을 최대화하면 이상치에 강건(robust)해지는 효과가 존재한다.</li>
<li>SVM은 스케일에 민감하기 때문에 변수들 간의 스케일을 잘 맞춰주는 것이 중요
(스케일링이 안된 상태에선 스케일이 큰 특정 변수의 변동성에 굉장히 민감할 수 있음)</li>
<li>Sklearn의 standard scaler를 사용하면 스케일을 잘 맞출 수 있다 꼭 필요!</li>
</ul>
<h3 id="margin">margin</h3>
<p>margin은 support vector와 decision boundary 사이의 길이였다.</p>
<p>SVM에서는 Hard margin 과 Soft margin을 사용할 수 있다.</p>
<ul>
<li><p>Hard margin
두 클래스가 하나의 선으로 완벽하게 나누어진다.
결정경계를 넘어서서 존재할 수 없다.</p>
</li>
<li><p>Soft margin
일부 데이터들이 분류 경계선의 분류 결과에 반하는 것을 일정 수준 허용한다.
몇몇 데이터가 결정 경계를 넘어서서 존재할 수 있다.
C 페널티 파라미터를 통해 얼마나 허용해줄지를 조정할 수 있다. 
C가 작으면 페널티가 작으니까 더 많이 넘어갈 수 있고, margin이 커진다.
Margin은 더 넓지만 train set 의 오차는 더 커지는 trade-off가 발생한다.</p>
</li>
</ul>
<h3 id="수식">수식</h3>
<p>출처 <a href="https://ko.wikipedia.org/wiki/%EC%84%9C%ED%8F%AC%ED%8A%B8_%EB%B2%A1%ED%84%B0_%EB%A8%B8%EC%8B%A0">위키백과</a>에 잘 정리되어 있다. 그래도 이해하기 위해 따라써보자!
<img src="https://velog.velcdn.com/images/im_ngooh/post/9bdc52b8-aa45-4083-8ff6-9c14c88d81bc/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/c565f241-555f-476a-b8ee-02cb8c54b581/image.png" alt=""></p>
<p>위와 같은 데이터 집합에 대해서, yi는 데이터가 어느 집합에 포함되는지를 나타내는 값으로 1과 -1이다.
사진과 같이 나누어지는 데이터와 결정경계, margin이 존재할 때, 
결정경계는 다음과 같이 나타낼 수 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/979e6064-8f81-4ed1-98c6-cd7d37cb85ef/image.png" alt=""></p>
<p>또한, 서포트 벡터가 존재하는 벡터 역시 역시 우변이 +1, -1인 식으로 표현할 수 있다.
그렇다면, 두 벡터(hyperplane) 사이의 거리를 수식으로 구해보았을때, 이는 마진을 의미하는 값이며, <img src="https://velog.velcdn.com/images/im_ngooh/post/c67c234a-ebc9-4159-9dc6-14d84afba189/image.png" alt="">
이다.</p>
<p>그렇다면, 결정경계와 마진 사이엔 데이터가 존재하지 않아야 하므로, 이를 조건식으로 나타낼 수 있고, 결국 마진을 최대화 해야하는 서포트 벡터 머신 문제는 아래와 같은 수식을 통해 표현할 수 있다고 한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/ef1d58d9-83aa-4000-b6a4-468b6af37064/image.png" alt=""></p>
<p>하지만 이때, ||w||가 루트를 포함하고 있으므로 풀기 어렵다. 따라서 이를 제곱으로 치환해도 해는 변하지 않으므로 다음과 같이 문제가 정의된다고 한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/b6377ee1-c939-478e-b347-0e3197a423d7/image.png" alt=""></p>
<p>soft margin의 경우, 결정경계를 넘어가서 존재하는 데이터 샘플들의 결정경계까지의 거리를 프사이라고 하였을때, 다음과 같은 식을 통해 문제가 정의된다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/a163a23c-4ea5-4577-8c0f-526d0e04bb46/image.png" alt=""></p>
<h3 id="nonlinear-svm">nonlinear SVM</h3>
<p>일반적인 SVM의 경우, 선형적으로 평면을 그려주어 데이터들을 분류한다.
그러나, 선형적으로 분류할 수 없는 데이터들이 존재하는 비선형 문제에 대해서도 SVM을 사용할 수 있다. 비선형적인 평면을 그려줄 수 있다는 뜻이다!
바로 <code>kernel</code>을 이용하면 된다.</p>
<p>커널이란, 데이터의 차원을 높여줄 수 있는 변환 함수이다. 
<a href="https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-2%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0-SVM">여기</a>를 참고해야겠다!</p>
<p>예를 들어 한 가운데 원의 형태를 이루며 존재하는 데이터 클래스 A들과 그 밖에 존재하는 클래스 B 데이터들이 있다면, z = x^2 + y^2라는 식을 세운 후 xz평면에 데이터들을 표시한다. 그렇다면 해당 차원에서는 데이터들이 선형 평면을 통해 나눠지게 된다.
-&gt; 고차원에서 linear 한 구분선이 저차원에서는 non-linear하게 표시된다는 것이다!</p>
<p>따라서 저차원 공간을 고차원 공간으로 변환해주어 선형 구분선을 그린다면 저차원공간에 비선형적인 구분선을 그려 SVM을 사용할 수 있다.</p>
<p>kernel에는 다양한 종류의 함수가 존재한다고 한다. 이건 차차.. 필요하면 알게 되겠ㅈ!
강의에서는 polynomial kernel과 Gaussian RBF(Radial Basis Function) kernel이라는 것이 존재한다 까지 다루셨다. Gaussian을 많이 사용한다고 한다!</p>
<p>scikit-learn에서는 kernel 이라는 하이퍼파라미터를 통해 설정할 수 있고, gamma라는 하이퍼파라미터를 통해 고차항 차수에 대한 정도, 즉 복잡도를 조절할 수 있다. C를 통해 앞에서 알아본 C 페널티도 조절할 수 있다.</p>
<h3 id="svm-regression">SVM Regression</h3>
<p>SVM을 통해 회귀 역시 진행할 수 있다.</p>
<p>분류와 마찬가지로 회귀 식(결정경계의 역할)에 대해 이와 평행한 오차 경계선을 두고, 회귀식과 관측치 사이 어느 정도의 오차까지는 허용하되, 오차가 그 이상으로 넘어가는 것은 허용하지 않는 방식으로 SVM을 사용해 회귀식을 예측한다.
오차 한계선과 회귀식 사이의 너비가 최대가 되도록 하고, 그 한계선을 넘어가는 관측치들에 대해서는 입실론을 통해 패널티를 부여한다.</p>
<p>비선형적인 회귀 선을 가지는 데이터들에 대해서도 유연하게 SVM을 이용해 회귀 예측을 진행할 수 있다. kernel을 이요한 비선형적 SVM을 사용한다. 입력변수들이 고차원의 공간에서 선형적인 회귀식을 구성하고, 이것들이 본 차원의 공간에서는 비선형적으로 구성되는 것과 같은 효과를 내는 테크닉을 이용한다!</p>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/1342f65a-5dbb-4f91-a3fd-acbb491f009c/image.png" alt="">
위와 같이 수식으로 나타낼 수 있다.</p>
<p>soft margin을 사용할 경우에는 프사이를 추가로 도입하여 사용하면 되겠다.</p>
<h3 id="scikit-learn-에서">scikit-learn 에서</h3>
<ul>
<li>SVC<pre><code class="language-python">from sklearn.svm import SVC
</code></pre>
</li>
</ul>
<p>clf = make_pipeline(StandardScaler(), SVC(gamma=&#39;auto&#39;))
clf.fit(X, y)</p>
<p>print(clf.predict([[-0.8, -1]]))</p>
<pre><code>[공식문서](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html)

C, kernel, degree, gamma 등의 하이퍼파라미터를 조정할 수 있다.

- SVR
```python
from sklearn.svm import LinearSVR, SVR

regr = make_pipeline(StandardScaler(), SVR(C=1.0, epsilon=0.2))
regr.fit(X, y)

# 또는
regr = make_pipeline(StandardScaler(),
                     LinearSVR(random_state=0, tol=1e-5))
regr.fit(X, y)
</code></pre><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVR.html">공식문서</a></p>
<p>kernel, gamma, epsilon, coef0 등의 하이퍼파라미터를 조정할 수 있다.</p>
<hr>
<p>참고자료</p>
<p><a href="https://ko.wikipedia.org/wiki/%EC%84%9C%ED%8F%AC%ED%8A%B8_%EB%B2%A1%ED%84%B0_%EB%A8%B8%EC%8B%A0">https://ko.wikipedia.org/wiki/%EC%84%9C%ED%8F%AC%ED%8A%B8_%EB%B2%A1%ED%84%B0_%EB%A8%B8%EC%8B%A0</a>
<a href="https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-2%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0-SVM">https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-2%EC%84%9C%ED%8F%AC%ED%8A%B8-%EB%B2%A1%ED%84%B0-%EB%A8%B8%EC%8B%A0-SVM</a>
<a href="https://mldlcvmjw.tistory.com/204?category=935400">https://mldlcvmjw.tistory.com/204?category=935400</a>
<a href="https://leejiyoon52.github.io/Support-Vecter-Regression/">https://leejiyoon52.github.io/Support-Vecter-Regression/</a></p>
<hr>
<p>어렵다. 거의 맛보기 수준으로 한거 같은데... 앞으로 공부할게 많구나!
열심히 해야겠다 진짜...!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 50] Ensemble]]></title>
            <link>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%EC%A0%84-Ensemble</link>
            <guid>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%EC%A0%84-Ensemble</guid>
            <pubDate>Tue, 22 Nov 2022 04:48:17 GMT</pubDate>
            <description><![CDATA[<p>11.22. 오전
어제에 이어 <a href="http://www.kmooc.kr/courses/course-v1:SSUk+SSMOOC20K+2022_T1/course/">KMOOC 강의</a> 수강!
오전에는 Ensemble에 대해서 공부하고, 오후에는 Support Vector Machine에 대해 공부해보려 한다.</p>
<p>시작!</p>
<hr>
<h1 id="ensemble">Ensemble</h1>
<p>일련의 분류나 회귀모델로부터 예측을 수집하면 가장 좋은 모델 하나보다 더 좋은 예측 성능을 얻을 수 있고, 이걸 앙상블 학습이라고 한다.
-&gt; 여러 모델의 결과들을 다 종합하여 최선의 결과를 내보자! 라는 컨셉 (집단지성) 결국, 투표 기반 분류기라고 할 수 있다.(회귀도 가능하다)</p>
<ul>
<li>일반적으로 다양한 머신러닝 기법들을 앙상블 시켜주면 성능이 향상되는 효과를 얻을 수 있다.</li>
<li>캐글에서 1등한 사람들을 보면 대부분 앙상블 기법을 사용했다.</li>
<li>tree기반이 많은데, tree가 수직 분할만 가능하고 일반화도 쉽게 되지 않는 반면, 여러 모델들의 조합, 투표로 만들어진 ensemble 모델은 비선형적인 분할도 가능하다.</li>
<li>다만, 해석력이 Tree 모델보다 떨어질 수 밖에 없다는 단점이 존재한다.</li>
</ul>
<h2 id="ensemble-learning-이론">Ensemble learning 이론</h2>
<ul>
<li><p>Weak Learner and Strong Learner
다수결 투표 분류기(앙상블)는 앙상블에 포함된 개별 분류기 중 가장 뛰어난 것 보다도 정확도가 높은 경우가 많다
그 개별 분류기들을 Weak learner(랜덤 추측보다 조금 더 높은 성능을 내는 분류기), 앙상블 모델을 Strong learner라고 부른다.
결국, 앙상블은 Weak Learner들을 조합하여 Strong Learner를 만드는 것이다.</p>
</li>
<li><p>수학적인 원리
동전 하나가 앞면이 나올 확률이 51%, 뒷면이 49%일 때, 한번 던졌을 때 앞면이 다수일 확률은 51%이지만, 천 번 던졌을 때 앞면이 다수일 확률은 75%에 육박한다. 많이 던질수록 확률은 1로 수렴해 갈 것이다.
저 동전을 분류기라고 생각했을 때, 이론적으로 100% 정확도를 갖는 분류기를 만들 수도 있다.
물론 이 설명은 이론적인 것일 뿐, 앙상블의 핵심 원리를 설명해주는 것이다.
모든 분류기가 완벽하게 독립적이고 오차에 상관관계가 없다는 가정 하의 이야기이다.</p>
</li>
<li><p>앙상블로 효과를 보려면 다양한 분류기를 만드는 것이 중요하다.
다양한 분류기를 만드는 첫번째 방법은 각기 다른 훈련 알고리즘들을 사용하여 앙상블을 진행하는 것이고,
두번째는 training data의 subset을 무작위로 구성하여 분류기를 각기 다르게 학습시키는 방법이다.</p>
</li>
<li><p>각각의 Tree들이 예측한 결과물을 다수결을 한다던지, 가중치를 줘서 가중합을 한다던지하는 방법으로 종합하여 최종 결과물을 낸다.</p>
</li>
</ul>
<h2 id="앙상블-기법의-종류">앙상블 기법의 종류</h2>
<h3 id="bagging">Bagging</h3>
<p>Bootstrap + aggregating
Bootstrap이란, 랜덤 복원 추출을 의미한다.</p>
<p>즉, 랜덤 추출을 통해 원래 데이터의 사이즈와 같은 샘플들을 여러 개 추출하는데, 추출의 과정이 복원 추출로 이루어진다.
이렇게 만들어낸 여러 개의 샘플에 대해 각각 모델을 학습시켜, 해당 모델들의 결과를 이용해 최종 모델을 만들어내는 것이 바로 Bagging이다.</p>
<ul>
<li><p>Bagging의 경우, 여러 모델들의 학습이 동시에, 병렬적으로 진행된다.</p>
</li>
<li><p>오버피팅 문제에 사용하기 적합하다.</p>
</li>
<li><p>bootstrap(복원 추출)을 이용하기 때문에, 편향은 유지하며 예측 모형의 분산을 최소화하여 예측력을 향상한다고 한다.</p>
</li>
<li><blockquote>
<p>수업시간에 예시로 들어주신 것처럼, 랜덤포레스트를 생각해보자.
한 개의 결정 트리는 데이터에 있는 노이즈에 대해 매우 민감하겠지만, 랜덤포레스트에서 트리들 사이에 상관관계가 존재하지 않는다면, 여러 트리들의 평균은 그런 노이즈에 대해 강인할 것이다. 이게 편향은 유지하며 분산은 최소화한다는 것이다.
따라서 오버피팅을 줄일 수도 있다.</p>
</blockquote>
</li>
<li><p>OOB
부트스트랩 과정 중 한 번도 샘플링 되지 않은 데이터들이 존재할텐데, 이것들을 OOB(Out-of-Bag)이라고 한다.
해당 데이터들을 마치 validation set 처럼 이용할 수 있다.</p>
</li>
<li><p>Pasting
Bagging과 유사하나, 복원추출이 아닌 비복원추출을 통해 샘플링을 진행한다.</p>
</li>
</ul>
<h3 id="boosting">Boosting</h3>
<p>여러 weak learner들을 순차적으로 연결해, 이전 학습기의 잔차를 보완해나가면서 학습해나갈 수 있도록 한 알고리즘이다.
즉, 앞선 학습기에서 제대로 해내지 못한 부분에 대해 가중치를 두어 boosting한다.</p>
<p>이 개념까지는 이해가 되는데. 그걸 어떻게 한다는건지 대체 모르겠다.. 아무리 찾아봐도 모르겠다. 공부하다보면 언젠가 알게 되겠지...?</p>
<p><a href="https://zephyrus1111.tistory.com/224">이 블로그</a>에서 gradient boosting에 대해 좀 설명해주신 것 같은데.. 어렵다...! 대단하셔라...
모델에 실제값과 예측값을 줄여주는 함수 h(x)와 학습률 l을 곱한 값을 더해가며 다음 모델을 만든다고 생각하면 될 것 같다. (이 h 자체도 머신러닝 모델인 것 같고?)</p>
<p>목요일 으쌰 복습에서 정리해준 걸 봤더니 이렇게 정리해주었다.</p>
<ol>
<li>간단한 모델 A를 통해 y를 예측</li>
<li>예측하고 남은 잔차 (residual)을 다시 B라는 모델을 통해 예측</li>
<li>A+B 모델을 통해 y를 예측</li>
</ol>
<ul>
<li>모델의 학습이 순차적으로 진행된다.</li>
<li>데이터에 가중치를 부여한다.</li>
<li>개별 트리의 성능이 낮은 underfitting에 적합하다.</li>
<li>앞에서부터 순차적으로 학습하므로 overfitting될 우려가 있다.</li>
<li>시간이 오래걸린다.</li>
</ul>
<p>-&gt; 개별 결정 트리의 낮은 성능이 문제라면 boosting이 적합하고, 오버피팅이 문제라면 bagging이 적합하다!</p>
<h3 id="voting">Voting</h3>
<ul>
<li><p>Hard Voting
다수의 분류기들 간 다수결을 통해 최종 클래스를 선정하는 방법.
가장 많은 분류기들이 예측한 값이 최종 앙상블 모델의 예측값이 된다.</p>
</li>
<li><p>Soft Voting
다수의 분류기들이 예측한 &#39;확률값의 평균&#39;을 통해 최종 클래스를 선정하는 방법
분류기들이 예측한 각 클래스의 평균 확률이 높은 쪽이 앙상블 모델의 예측값이 된다.</p>
</li>
<li><p>이 외에도 가중치를 두어 투표하는 등의 방법이 있다.</p>
</li>
</ul>
<h2 id="앙상블-모델">앙상블 모델</h2>
<h3 id="randomforest">RandomForest</h3>
<p>DecisionTree를 Bagging하여 만들어진 앙상블의 대표적인 모델이다.</p>
<p>사이킷런에서 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택하여 해당 특성들 중에서 최선의 분할을 찾아가는 방식으로 각각의 트리를 분할한다. RandomForestRegressor는 분할에 전체 특성을 사용한다고 한다.</p>
<p>-&gt; 분류일때는 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 한다.
-&gt; 회귀일때는 각 트리의 예측을 평균한 값을 예측으로 한다.</p>
<p>oob_score = True를 인자로 준다면, .oob_score_ 메소드를 통해 OOB점수를 알 수 있다.</p>
<h3 id="extratrees">ExtraTrees</h3>
<p>엑스트라 트리는 랜덤포레스트와 유사하지만, 각 결정트리를 만들때 전체 훈련 데이터를 사용하여 만든다. 즉, 부트스트랩을 사용하지 않는 것이다.
거기에 더해, 각 결정트리가 최선의 분할을 찾아가는 것이 아니라 무작위의 분할을 시행한다.</p>
<p>결론적으로 전체 훈련 데이터를 사용하는 여러개의 트리로 구성되는데, 각 트리는 최선의 분할이 아닌 임의의 분할을 통해 학습과 예측을 진행하는 것이다.</p>
<p>DecisionTree를 만들때 splitter = &#39;random&#39;으로 지정한다면 ExtraTree가 되는데(ExtraTreeClassifier), Decision Tree가 아닌 이것들이 모여있다고 볼 수 있다.</p>
<p>엑스트라트리는 무작위성이 크기 때문에 랜덤포레스트보다 더 많은 결정트리를 훈련해야할 필요가 있다.
그러나, 랜덤하게 노드를 분할하기 때문에 계산속도가 랜덤포레스트보다 빠르며, 많은 트리를 앙상블하여 과대적합을 막을 수 있다.</p>
<ul>
<li>VotingClassifier
사이킷런 공식 문서 예제 참고<pre><code class="language-python">from sklearn.ensemble import VotingClassifier
</code></pre>
</li>
</ul>
<p>clf1 = LogisticRegression(multi_class=&#39;multinomial&#39;, random_state=1)
clf2 = RandomForestClassifier(n_estimators=50, random_state=1)
clf3 = GaussianNB()</p>
<p>eclf1 = VotingClassifier(estimators=[
        (&#39;lr&#39;, clf1), (&#39;rf&#39;, clf2), (&#39;gnb&#39;, clf3)], voting=&#39;hard&#39;)
eclf1 = eclf1.fit(X, y)
print(eclf1.predict(X))</p>
<pre><code>[공식문서](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.VotingClassifier.html)

- BaggingClassifier
사이킷런 공식 문서 예제 참고
```python
from sklearn.svm import SVC
from sklearn.ensemble import BaggingClassifier

clf = BaggingClassifier(base_estimator=SVC(),
                        n_estimators=10, random_state=0).fit(X, y)
clf.predict([[0, 0, 0, 0]])</code></pre><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.BaggingClassifier.html">공식문서</a></p>
<ul>
<li><p>GradientBoostingClassifier
깊이가 얕은 결정트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블 하는 방법.
기본적으로 깊이가 3인 결정트리를 100개 사용한다고 한다. 따라서 과대적합에 강하고 높은 일반화 성능을 기대할 수 있다.
트리를 앙상블에 추가하는 과정에서 경사하강법을 사용한다. 손실함수로는 로지스틱 손실함수와 MSE를 사용한다.</p>
<pre><code class="language-python">from sklearn.ensemble import GradientBoostingClassifier

clf = GradientBoostingClassifier(n_estimators=100, learning_rate=1.0,
  max_depth=1, random_state=0).fit(X_train, y_train)
clf.score(X_test, y_test)</code></pre>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html">공식문서</a></p>
</li>
</ul>
<ul>
<li>xgboost, lightgbm, catboost
천천히 공부해보자...</li>
</ul>
<hr>
<p><a href="https://zephyrus1111.tistory.com/224">https://zephyrus1111.tistory.com/224</a>
<a href="https://tensorflow.blog/2017/11/30/%EB%8D%94%EC%9A%B1-%EB%9E%9C%EB%8D%A4%ED%95%9C-%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8-%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%A6%BC-%EB%9E%9C%EB%8D%A4-%ED%8A%B8%EB%A6%ACextratreesclassifier/">https://tensorflow.blog/2017/11/30/%EB%8D%94%EC%9A%B1-%EB%9E%9C%EB%8D%A4%ED%95%9C-%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8-%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%A6%BC-%EB%9E%9C%EB%8D%A4-%ED%8A%B8%EB%A6%ACextratreesclassifier/</a>
<a href="https://itstory1592.tistory.com/16">https://itstory1592.tistory.com/16</a>
<a href="https://m.blog.naver.com/fbfbf1/222432485622">https://m.blog.naver.com/fbfbf1/222432485622</a>
<a href="https://erdnussretono.tistory.com/49">https://erdnussretono.tistory.com/49</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 49] KNN, 로지스틱 회귀, Decision Tree]]></title>
            <link>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%ED%9B%84-KNN-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80-Decision-Tree</link>
            <guid>https://velog.io/@im_ngooh/11.22.-%EC%98%A4%ED%9B%84-KNN-%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1-%ED%9A%8C%EA%B7%80-Decision-Tree</guid>
            <pubDate>Mon, 21 Nov 2022 08:47:34 GMT</pubDate>
            <description><![CDATA[<p><a href="http://www.kmooc.kr/courses/course-v1:SSUk+SSMOOC20K+2022_T1/course/">K-MOOC 실습으로 배우는 머신러닝</a>
11.21 두 번째 시간
이번에는 KNN, 로지스틱 회귀 등 수업에서 다루지 않았던 모델들의 개요에 대해 살펴보았고,
Decision Tree의 원리와 작동 방식에 대해 더 이해해보는 시간을 가졌다!</p>
<hr>
<h1 id="knn-k-nearest-neighbors">KNN (K-Nearest Neighbors)</h1>
<p>classifier의 대표적인 모델
굉장히 직관적이며 간단하고, 이해하기도 쉬운데 성능도 꽤 괜찮은 알고리즘이라고 한다!
어떤 데이터가 주어지면, 그 주변의 데이터를 살펴본 뒤 더 많은 데이터가 포함되어 있는 범주로 분류한다.</p>
<h3 id="컨셉">컨셉</h3>
<p>이는 관측치들 끼리의 거리가 가까우면, Y도 역시 비슷할 것이라는 가설을 기반으로 한다. 따라서 새로운 데이터가 들어왔을때, 주변 K개의 데이터의 class를 조사하여, 다수결의 원칙(majority voting)에 따라 더 많은 쪽이 속해있는 class로 해당 데이터를 분류한다.</p>
<h3 id="하이퍼파라미터">하이퍼파라미터</h3>
<p>K값을 하이퍼파라미터로써 바꾸어주며 모델을 조정할 수 있다.
K가 클 수록 모델의 complexity가 떨어질 것이며, K가 작을수록 complexity가 클 것이다. K가 너무 크다면 underfitting, 작으면 overfitting이 생긴다.
일반적으로 홀수를 사용한다. (짝수이면 동점이 나올 수 있으므로)</p>
<h3 id="특징">특징</h3>
<p>기본 함수나 수식이 있는 다른 모델들과는 다르게, 이는 거리를 계산하여 적용하는 방식이다.
따라서 미리 학습을 할 필요 없이, testing 할 데이터가 들어오면 training data와의 거리를 구하고 최종 결과를 내놓는 이 모델은 lazy learning algorithm 이라고 부르기도 한다.
위와 같은 특징으로 인해 실시간적으로 큰 데이터에 대해서 사용하기는 어려울 수 있다.
최적의 K값은 validation set 등을 이용해 경험적으로 알아내야 한다. bias-variance trade off 를 고려하여 정한다.</p>
<h3 id="거리-측정-공식">거리 측정 공식</h3>
<p>KNN에서 가장 중요한 것 중 하나가 바로 거리 측정 공식이다.</p>
<ol>
<li><p>유클리드 거리(Euclidean Distance)
우리가 일반적으로 생각하는 점과 점 사이의 거리를 구하는 공식이다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/27ee5c4d-391b-45fc-8c13-00e9ccb39cde/image.png" alt=""></p>
</li>
<li><p>맨해튼 거리(Manhattan Distance)
점들 사이의 직선 거리가 아닌, 각 축 별 거리를 합쳐준 거리이다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/2b2d08cd-17e8-48c1-a35a-59bb5752d741/image.png" alt=""></p>
</li>
</ol>
<p>보통 유클리드 거리를 많이 사용하지만, 측정하는 대상에 대해 완벽히 독립적으로 생각하여 변수별로 거리를 계산하고자 할 때에는 맨해튼 거리를 사용한다고 한다.</p>
<h3 id="scikit-learn에서">scikit-learn에서</h3>
<pre><code class="language-python">from sklearn.neighbors import KNeighborsClassifier</code></pre>
<p>위와 같이 import 하여 사용할 수 있다!
<a href="https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html">공식문서</a>
<code>n_neighbors</code>가 K값을 의미한다.
<code>weights</code>에 <code>{‘uniform’, ‘distance’}</code>를 통해 거리에 따른 가중치를 줄지 말지를 결정할 수 있다.</p>
<hr>
<h1 id="로지스틱-회귀">로지스틱 회귀</h1>
<p>로지스틱회귀란, 선형회귀 모델의 classification 버전이다!
그냥 선형회귀 모델만 사용하는 것이 아니라, 선형회귀 모델의 output을 logistic function을 이용해 변환하여 사용함으로써, 분류의 효과를 내므로 logistic regression이라고 부른다.</p>
<h3 id="필요성">필요성</h3>
<p>종속변수가 (0,1)의 값만 가지는 binary 형식일때, 회귀를 통해 이를 분석하는 것이 타당할까?
-&gt; 선형회귀분석의 우변(회귀식)은 범위에 제한이 없지만, 좌변(종속변수)의 경우 0,1 이라는 범위의 제한이 있기 때문에 사용이 적절하지 않다.
회귀 분석을 진행할 시 엉망인 결과가 나올 것이다!</p>
<p>따라서, 이진 형태를 가지는 종속변수의 예측(분류 문제)에 대해 회귀식을 통해 모형을 추정하기 위해서 logistic regression이 필요하다.</p>
<p>분류문제임에도 불구하고 굳이 회귀식을 이용하려는 이유는?
회귀식으로 표현할 경우, 변수의 통계적 유의성 분석 및 종속변수에 미치는 영향력 등을 알아볼 수 있기 때문이다!</p>
<h3 id="컨셉-1">컨셉</h3>
<ul>
<li>로지스틱 함수(sigmoid)
<img src="https://velog.velcdn.com/images/im_ngooh/post/c52999df-21f6-40d3-ae24-f189b3ba0c1a/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/599395a5-6762-45dd-bf1a-3c63699af47a/image.png" alt=""></li>
</ul>
<p>sigmoid function을 이용하면, 회귀식을 이용하면서도 종속변수의 값의 범위를 0~1 사이로 제한할 수 있다.</p>
<p>따라서, 회귀식으로 분류의 효과를 내기 위해, 회귀식의 결과를 sigmoid function에 넣어준다. 그렇다면 해당 식의 결과는 특정 클래스로 분류 될 확률을 의미할 것이다.</p>
<h3 id="loss-함수">Loss 함수</h3>
<p>logistic regression의 loss 함수로는 Cross-entrophy를 주로 이용한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/8697b1c9-af90-4b18-973e-349058b2399c/image.png" alt="">
사진 출처 : K-MOOC 강의 자료</p>
<p>-(실제 클래스 * 확률값에 로그를 취한 값을 모든 클래스에 더해준 값) 이다.
결국, 해당하는 클래스의 확률값에 로그를 취한 값(들을 더한 값)이 cross entrophy이다! 확률은 0에서 1 사이일거고, 거기서 값이 커질수록 로그값은 작아진다. 여기에 -가 붙어있기 때문에, cross entrophy가 작다는 것은, 확률이 1에 가까워진다는 것!</p>
<p>즉, loss를 minimize 해주게 되면, 실제 클래스로 분류 될 확률이 최대화된다!</p>
<p>강의에서는 cross - entrophy라고 배웠는데. 인터넷 찾아보다보니
Log Loss를 많이 사용한다고 한다.
<a href="https://developers.google.com/machine-learning/crash-course/logistic-regression/model-training">참고</a>해서 더 공부해보자!
<img src="https://velog.velcdn.com/images/im_ngooh/post/1f5c4a87-5c51-46c5-adc4-2c7d5f0375b8/image.png" alt="">
사실, 위에서 사용한 식과 동일하다! 이건 천천히 좀 더 알아봐야겠다.....
조금 찾아봤는데, 정확하진 않지만 같은 식을 가지고 이진 분류일 경우 Log Loss function, 다중 분류에도 사용 가능한 경우 Cross-entrophy loss function이라고 하는 것 같다!</p>
<h3 id="scikit-learn에서-1">scikit-learn에서</h3>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html">공식문서</a></p>
<pre><code class="language-python">from sklearn.linear_model import LogisticRegression</code></pre>
<p>로 사용할 수 있다!</p>
<p>되게 다양한 하이퍼파라미터들이 있는데.. 뭔지 잘 모르겠다.... 천천히 찾아보자!
<code>.decision_function()</code> method를 사용하면, 양성 클래스에 대한 z값을 반환한다.
<code>predict_proba</code>등을 이용해 확률을 얻을 경우, 클래스 명은 알파벳 순으로 자동 정렬된다. 
선형회귀인 만큼 <code>.coef_[]</code>를 통해 해당 위치의 계수를 볼 수 있으며, <code>.intercept_</code>를 통해 y 절편값 역시 확인할 수 있다.</p>
<p>이진분류의 경우 시그모이드 함수를 사용해 z값을 변환하지만,
다중 분류의 경우 softmax 함수를 사용하여 z값을 확률로 변환한다.
이때, softmax 함수란 여러개의 선형 방정식의 출력값을 0~1 사이로 압축하고 전체 합이 1이 되도록 만들어진 함수라고 한다. 이를 위해서 지수함수를 사용한다. <a href="https://wikidocs.net/35476">참고</a> 
시그모이드가 1 / 1 + e^(-z)였다면, 소프트맥스는 e^(z1) / (e^(z1) + e^(z2) + ... + e^(zn))이다.
나중에 딥러닝을 배울때 나온다고 하니! 알아두자!</p>
<p>추가로, KNN에서 predict_proba를 이용하면 로지스틱 회귀를 이용한 것과 마찬가지로 각 클래스로 분류될 확률을 구할 수 있다.</p>
<hr>
<h1 id="decision-tree">Decision Tree</h1>
<p>Decision Tree는 그동안 수업시간에 많이 다루었지만, 뭔가 정확한 작동원리를 파악하고 있지 못하는 느낌이었다!
이번 수업을 들으면서, Decision Tree와 Decision tree regression의 좀 더 자세한 작동 원리와, 데이터 공간 측면에서의 이해를 할 수 있었다.</p>
<h3 id="decision-tree란">Decision tree란?</h3>
<p>분류와 회귀 작업 및 다중출력 작업도 가능한 다재다능한 머신러닝 방법론
IF_THEN 룰에 기반해 진행하여, 해석력이 아주 좋다!
CART(Classificatio and Regression tree) 알고리즘으로, 분류와 회귀 모두에 사용할 수 있다.</p>
<h3 id="학습-과정">학습 과정</h3>
<p>분기마다 변수와 기준을 세워 클래스들을 분류해나가는 과정을 통해 학습을 진행한다.
한번에 한 개의 변수를 사용하여 정확한 예측이 가능한 규칙들의 집합을 생성한다고 볼 수 있다.
IF then 형식으로 표현되는 규칙이 만들어진다.
예를 들어,
내일 날씨가 맑고, 습도가 70% 이하이면 아이는 밖에 나가서 놀 것이다.
내일 비가 오고 바람이 불면 아이는 밖에 나가 놀지 않을 것이다. 와 같은 규칙을 토대로 분류가 이루어질 수 있다.
이와 같은 학습 방법으로 인해 Decision tree 모델은 해석력이 우수하다고 할 수 있다.</p>
<h3 id="데이터-공간-측면">데이터 공간 측면</h3>
<p>Decision Tree에서, 데이터 공간 측면으로 보면 수직 분할이 이루어진다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/58cf915e-50c6-49ac-b2ef-37d1dee39106/image.png" alt="">
이렇게!
<img src="https://velog.velcdn.com/images/im_ngooh/post/2773aded-4923-4949-8c47-4c72617b8020/image.png" alt=""></p>
<h3 id="분할의-방법">분할의 방법</h3>
<p>데이터 공간의 순도가 증가되게끔 영역을 구분하는 방법이 바로 잘 분할하는 방법이다.
실제로는 어떻게 찾지? 불순도가 높은 영역을 찾아 관측치들 사이에서 후보군들로 경계선을 만들어 본다. 그 중에서 가장 순도를 높여주는 영역을 찾아 그어주면 된다. 
데이터 공간 측면에선, 가로로도 세로로도 구분할 수 있다. 즉, 각 변수마다 구분할 수 있다.
따라서 각 변수마다 구분할 수 있는 영역을 찾아 구분해본 뒤 순도가 높게 잘 구분되는 것을 찾아 구분한다.
저렇게 분류에 대한 학습을 한 후!
새로운 test data가 들어왓을 때 해당하는 구역의 class로 분류해준다.</p>
<h3 id="불순도">불순도</h3>
<ul>
<li><p>한 노드에 속하는 샘플들의 클래스 비율을 이용해 특정 노드가 얼마나 잘 구분되었는지 측정하는 지표</p>
</li>
<li><p>지니 계수
1 - (음성 클래스 확률^2 + 양성 클래스 확률^2)
다중 분류일 경우에도 동일하다.
노드에 하나의 클래스만 있다면 지니 불순도는 0이 되므로 가장 작다.
만약 클래스가 무한히 많고, 각각의 확률이 같다면 불순도가 1에 가까워질 수도 있다!</p>
</li>
<li><p>entropy
지니 계수 말고 결정트리에서 불순도가 될 수 있는 값. 정보 엔트로피 혹은 섀넌 엔트로피로 배웠었다! 
<img src="https://velog.velcdn.com/images/im_ngooh/post/b8f5f088-742e-46d9-958b-b7937455f28c/image.png" alt="">
데이터에 포함되어 있을 것으로 기대되는 평균 정보량을 의미했었다. 결국 불확실성이며 불순도이다.</p>
</li>
<li><p>정보 이득
부모 노드와 자식 노드 사이의 불순도 차이. 결정 트리 알고리즘은 정보 이득이 최대가 되도록 데이터를 나눈다.</p>
</li>
</ul>
<h3 id="cart-알고리즘">CART 알고리즘</h3>
<p>CART란 Classification and Regression Tree를 의미했었다.
이는 불순도를 최소화하도록 최종 노드를 계속 이진 분할하는 방법론을 의미한다.
최대 깊이가 되거나, 불순도를 줄이는 분할을 더 이상 찾을 수 없을때까지 트리를 계속 분할한다.</p>
<p>CART 알고리즘의 지니계수와 관련된 식이 존재한다. 
<img src="https://velog.velcdn.com/images/im_ngooh/post/4796b0f2-d785-47da-b0d1-ec1b2f2f3c35/image.png" alt=""></p>
<p>m은 각각의 서브셋으로 나누어진 샘플의 수를 의미한다.</p>
<h3 id="regularization">Regularization</h3>
<ul>
<li>Decision Tree 모델은, 훈련 데이터에 대한 제약 사항이 존재하지 않아 과대 적합이 일어나기 쉽다. 리프노드에 속한 데이터의 개수가 하나라면 이건 지나친 일반화가 일어났다고 볼 수 있을 것이다.</li>
<li>따라서 훈련에 제약을 둠으로써(regularization) 과대적합을 방지할 수 있다.</li>
<li>그렇기 위해서 사용하는 파라미터들이 존재한다.
max_depth : 트리의 최대 깊이
min_samples_split : 분할되기 위해 노드가 가져야하는 최소 샘플 수
min_samples_leaf : 리프 노드가 가지고 있어야 할 최소 샘플 수
max_leaf_nodes : 리프 노드의 최대 수
등이 존재한다.    </li>
</ul>
<h2 id="decision-tree-regression">Decision tree regression</h2>
<p>여태까지 살펴본 내용은 분류의 경우 Decision Tree가 어떻게 동작하는지와 관련된 내용이었다.
CART 알고리즘인 만큼 회귀에도 동작할텐데, 어떤 방법으로 동작할까?
나머진 다 동일하지만, target Y 값을 처리하는데에만 차이가 있다.</p>
<p>분류의 경우, 나눠진 노드에 속한 관측값들의 클래스가 바로 분류의 결과가 되는 반면,
회귀의 경우, 나눠진 노드에 속한 관측값들의 타겟값의 평균이 바로 회귀의 결과이다.</p>
<p>분할할때 사용하는 불순도의 경우 MSE를 사용한다.
특이한 점이 있다면, 예측값이 상수라는 점이다!
MSE를 구할때 예측값은 평균인 상수이고, 노드에 속한 관측값들을 빼 제곱한 평균을 구하면 되었다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/5a1e445e-e4fa-495b-a5df-e80f27dbf9b5/image.png" alt=""></p>
<p>이 역시도 결정트리인 만큼 regularization을 잘 적용해주어야 한다!</p>
<hr>
<p>참고 자료</p>
<ul>
<li><a href="https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-6-K-%EC%B5%9C%EA%B7%BC%EC%A0%91%EC%9D%B4%EC%9B%83KNN">https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-6-K-%EC%B5%9C%EA%B7%BC%EC%A0%91%EC%9D%B4%EC%9B%83KNN</a></li>
<li><a href="https://datascienceschool.net/03%20machine%20learning/10.01%20%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1%20%ED%9A%8C%EA%B7%80%EB%B6%84%EC%84%9D.html">https://datascienceschool.net/03%20machine%20learning/10.01%20%EB%A1%9C%EC%A7%80%EC%8A%A4%ED%8B%B1%20%ED%9A%8C%EA%B7%80%EB%B6%84%EC%84%9D.html</a></li>
<li><a href="https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-4-%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%ACDecision-Tree">https://bkshin.tistory.com/entry/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-4-%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%ACDecision-Tree</a></li>
<li><a href="https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression">https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression</a></li>
<li><a href="https://ratsgo.github.io/machine%20learning/2017/03/26/tree/">https://ratsgo.github.io/machine%20learning/2017/03/26/tree/</a></li>
<li><a href="https://tyami.github.io/machine%20learning/decision-tree-4-CART/">https://tyami.github.io/machine%20learning/decision-tree-4-CART/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 49] 머신러닝 프로세스, 경사하강법]]></title>
            <link>https://velog.io/@im_ngooh/11.21-%EC%98%A4%EC%A0%84-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B2%BD%EC%82%AC%ED%95%98%EA%B0%95%EB%B2%95</link>
            <guid>https://velog.io/@im_ngooh/11.21-%EC%98%A4%EC%A0%84-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B2%BD%EC%82%AC%ED%95%98%EA%B0%95%EB%B2%95</guid>
            <pubDate>Mon, 21 Nov 2022 02:50:25 GMT</pubDate>
            <description><![CDATA[<p>11.21. 오전
<a href="http://www.kmooc.kr/courses/course-v1:SSUk+SSMOOC20K+2022_T1/video">KMOOC - 실습으로 배우는 머신러닝</a></p>
<p>중 머신러닝 프로세스 개요, 경사하강법 개요, 경사하강법 심화를 학습하였다.</p>
<hr>
<h1 id="머신러닝-프로세스-개요">머신러닝 프로세스 개요</h1>
<h2 id="머신러닝-프로세스">머신러닝 프로세스</h2>
<blockquote>
<h4 id="1-도메인-지식을-기반으로-데이터를-수집하고">1. 도메인 지식을 기반으로 데이터를 수집하고,</h4>
</blockquote>
<blockquote>
<h4 id="2-데이터에-대한-이해를-바탕으로-eda-및-데이터-전처리를-진행한다">2. 데이터에 대한 이해를 바탕으로 EDA 및 데이터 전처리를 진행한다.</h4>
</blockquote>
<blockquote>
<h4 id="3-모델에-학습을-시켜-모델에-적용하고">3. 모델에 학습을 시켜 모델에 적용하고</h4>
</blockquote>
<blockquote>
<h4 id="4-해당-모델을-검증한다">4. 해당 모델을 검증한다.</h4>
</blockquote>
<blockquote>
<h4 id="5-피드백을-바탕으로-모델이나-데이터-전처리-방식-등을-수정하여-원하는-성능을-얻을때까지-진행한다">5. 피드백을 바탕으로 모델이나 데이터 전처리 방식 등을 수정하여 원하는 성능을 얻을때까지 진행한다.</h4>
</blockquote>
<h2 id="데이터-관련-용어">데이터 관련 용어</h2>
<ul>
<li>Dataset : 정의된 구조로 모아져 있는 데이터 집합</li>
<li>Data point(Observation) : 데이터 세트에 속해있는 하나의 관측치</li>
<li>Feature(variable, attribute) : 데이터를 구성하는 하나의 특성, x</li>
<li>Label(target, response) : 입력변수들에 의해 예측, 분류 되는 출력 변수, y</li>
<li>관측치의 개수 : n, feature의 개수 : p로 주로 표현한다.</li>
</ul>
<h2 id="분류와-회귀">분류와 회귀</h2>
<ul>
<li>분류(classification) : 종속변수가 범주형일 때 사용하는 방법</li>
<li>회귀(regression) : 종속변수가 연속형일 때 사용하는 방법</li>
</ul>
<h2 id="데이터-준비-과정">데이터 준비 과정</h2>
<ul>
<li><p>Dataset Exploration(EDA) : 데이터 모델링을 하기 전에 데이터 변수 별 기본적인 특성들을 탐색하고 데이터의 분포적인 특징 이해. 데이터의 의미를 잘 파악한 후 머신러닝에 활용해야 한다. 데이터를 잘 살펴보고, 이에 적절한 머신러닝 모델을 선택하는 것이 아주 중요하다!</p>
</li>
<li><p>Missing value : 데이터를 수집하다 보면 일부 데이터가 수집되지 않고 결측치로 남아있는 경우가 있으므로 보정이 필요하다.</p>
</li>
<li><p>Data types and conversion : 데이터 셋 안에 여러 종류의 데이터 타입이 있을 수 있으므로, 이를 분석이 가능한 형태로 변환 후에 사용해야한다.</p>
</li>
<li><p>Normalization : 데이터 변수들의 단위가 크게 다른 경우들이 있고, 이러한 것들이 모델 학습에 영향을 주는 경우가 있어서 정규화 하는 것이 필요할 수 있다.</p>
</li>
<li><p>Outliers : 관측치 중에서 다른 관측치와 크게 차이가 나는 관측치들이 있고 이러한 관측치들은 모델링 전 처리가 필요할 수 있다.</p>
</li>
<li><p>Feature selection : 많은 변수 중에서 모델링을 할 때 중요한 변수가 있고 그렇지 않은 변수가 있어서 선택이 필요한 경우가 있다. 모델의 설명 가능성에 대해 이야기할 때에도 많이 사용된다.</p>
</li>
<li><p>Data sampling : 모델을 검증하거나 이상 관측치를 찾는 모델링을 할 때 또는 앙상블 모델링을 할 때 가지고 있는 데이터를 일부분 추출하는 과정을 거치기도 한다. 우리 실습에서는 사이즈가 너무 큰 데이터에 대해서 전 처리 및 EDA를 할 때, 일단 샘플링한 데이터를 통해 빠르게 진행해본 뒤 전체 데이터에 대해 적용하기도 했었다.</p>
</li>
</ul>
<p>대부분 머신러닝 과정 중 70% 시간은 데이터 준비에 들어가는 시간이다!
실제 모델에 학습을 시키고 적용하는 시간은 30% 뿐!</p>
<h2 id="데이터-모델링">데이터 모델링</h2>
<ul>
<li>모델은 입력 변수와 출력 변수 간의 관계를 정의해줄 수 있는 추상적인 함수 구조.</li>
<li>Training data 를 통해 모델을 학습하고, test data로 검증한다. 그 후 피드백을 통해 모델을 수정하거나, EDA와 전처리를 다시 해주는 등의 방법으로 원하는 성능이 나올 때까지 진행한다. </li>
<li>다양한 모델들을 사용할 수 있다.</li>
</ul>
<h2 id="모델링-검증">모델링 검증</h2>
<ul>
<li>Underfit : prediction error to training data (Loss) : 너무 간단하게 학습했다.</li>
<li>Overfit : predictiona error to validation data(Generalization error) : 너무 복잡하게 학습했다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/564c8c4e-36cd-4991-bbcf-90c57e1002f4/image.png" alt=""></li>
</ul>
<p>training error와 test error(validation error)간의 그래프</p>
<ul>
<li>test error가 최소가 되는 지점이 가장 적합한 복잡도 수준이다.</li>
<li>모델의 복잡도는 하이퍼파라미터 튜닝을 통해 조정할 수 있다.</li>
<li>bias-variance trade-off에 의한 현상이다.</li>
</ul>
<h3 id="검증-방법">검증 방법</h3>
<ul>
<li>Validation with training data only (X) : 거의 사용하지 않는다.</li>
<li>Training, test data 이용 -&gt; 하이퍼파라미터의 검증에 문제가 있다.</li>
<li>Training, validation, test data 이용 -&gt; hold out validation </li>
<li>Cross validation -&gt; 데이터의 수가 적어 hold out validation 을 진행하기 어려운 상황에서도 사용할 수 있다. 시간은 좀 오래걸리지만 검증의 정확도가 높다.</li>
<li>일반적으로는 hold out validation을 사용한다고 한다.</li>
</ul>
<p>그동안 배운 내용들을 리마인드해보며 머신러닝의 전체 프로세스를 되짚어볼 수 있는 시간이었다.</p>
<hr>
<h1 id="경사하강법">경사하강법</h1>
<p>어렵다!</p>
<h2 id="최적화optimization">최적화(Optimization)</h2>
<ul>
<li>최적화란? 
loss function을 최소로 만드는 머신러닝 모델을 얻어내는 것.</li>
</ul>
<h2 id="경사하강법-개요">경사하강법 개요</h2>
<p>경사하강법은 Iterative algorithm-based optimization 이다.
쉽게 생각하면, loss function의 기울기(gradient)가 작아지는 방향으로 반복적으로 이동하며 최소값에 도달하는 방법이다.</p>
<h3 id="필요성">필요성</h3>
<ul>
<li>손실 함수가 어떻게 생겼는지, 식이 무엇인지 파악할 수 없는 경우, 혹은 너무 복잡하여 미분이 불가능한 경우가 존재한다. 그럴 때 현재 알고 있는 것은 현재의 함수값, 그리고 몇가지 추가적인 정보 뿐이다. 이때 함수의 최소값을 찾기 위해 gradient - descent가 필요하다. 이를 이용하면 함수를 미분하여 최소값을 구하지 않고, 비교적 간단하게 최소값을 알아낼 수 있다.</li>
</ul>
<h3 id="경사하강법이란">경사하강법이란?</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/9ab8ef9b-763b-4ca5-90d5-93656321bee3/image.png" alt="">
최적화할 함수 f(x)에 대해서, 현재지점을 Xi라고 했을때, 다음 지점 Xi+1은 위와 같은 수식으로 구할 수 있다.
감마는 step size 혹은 learning rate로, 이동할 거리를 조정할때 사용하는 하이퍼파라미터이다.</p>
<p>식에 대해 이해해보면, 현재 지점에서 그 지점의 기울기(gradient)와 step size를 곱한 값을 빼준다. 
이는, 
방향에 대해서는 기울기의 반대 방향으로 이동해야 최소값에 다가갈 수 있기 때문이며,
크기에 대해서는 최소값으로 다가갈수록 graident의 크기가 작아지기 때문이다.</p>
<h3 id="step-size">step size</h3>
<p>적절한 step size를 찾는 것도 중요하다.</p>
<ul>
<li>만약 step size가 너무 크면? 
진동하여 최적해를 찾지 못할 가능성이 있다.</li>
<li>만약 step size가 너무 작으면?
최적해를 찾는 학습에 시간이 너무 오래 걸린다.</li>
</ul>
<h3 id="한계">한계</h3>
<p>경사하강법은 global minimum을 찾는 것을 보장할 수 없다.
만약 찾아가는 중간에 local minimum이 존재한다면, 거기서 멈추게 될 수 있기 때문이다.
하지만 local minimum도, 다른 지점에 비해 머신러닝의 성능이 좋게 나오는 것이 입증되었다고 한다.
또한, 너무 큰 데이터에 대해서는 시간이 너무 오래 걸린다는 단점도 존재한다.</p>
<h3 id="stochastic-gradient">stochastic gradient</h3>
<p>gradient descent 방법에 시간이 너무 오래걸린다는 단점을 극복하기 위해 사용하는 방법이다.
간단히 이해하면 데이터를 여러개의 batch로 나누어 각각에 gradient descent를 적용한다고 생각할 수 있다.
극단적으로는 하나의 샘플만 사용하기도 한다. 그러나 이 경우 오히려 시간이 오래걸릴수도 있다.</p>
<p>위 방법들은 성능은 유지하면서도 computational cost를 줄여 빠르게 해를 구할 수 있다는 장점이 있다.</p>
<h3 id="momentum">Momentum</h3>
<p>gradient descent를 통해 local minimum이 아닌 global minimum을 찾기 위해 더해주는 값. 관성이라는 뜻이다.
시간이 없어 찾아보진 못했지만, 관성이 있어, 원하는 만큼보다 더 가게 되었을 때, 그 부분이 local minimum이라면 그 반대 쪽으로 gradient 가 작아질 거니까...
local minimum에서 벗어나 global minimum을 찾을 수 있도록 더해주는 값이라고 이해했다.
특히 saddle point(안장점)에 대해서는 잘 벗어날 수 있다는 효과가 존재한다!</p>
<p>오후에 경사하강법 좀 더 찾아보고 시작하자!</p>
<p><a href="https://heytech.tistory.com/382">참고한 블로그</a>
Momentum에 대해 되게 잘 정리해주신 분이 있어 읽어봤다!</p>
<p>이를 토대로 추가적으로 이해해보면, 모멘텀이란 관성을 의미한다.
즉, &#39;이전&#39; 기울기의 방향 및 크기를 토대로, 해당 방향으로 관성을 가져 그만큼 추가로 이동하게 해주는 것이 바로 모멘텀이다. local minimum에 빠질 수 있는 상황에서 이러한 기법을 사용하면 추가로 이동하므로 빠져나갈 수 있다. global minimum에서는 빠져나갈 수 없고!</p>
<p>수식에 대해서 살펴보면, 
<img src="https://velog.velcdn.com/images/im_ngooh/post/651e56a2-2276-4d86-823c-7526e9e94642/image.png" alt=""></p>
<p>경사하강법에서 빼주는 값이 위 모멘텀으로 바뀐다.
관성계수와 그 전 모멘텀을 곱한 값에, 학습률과 그라디언트를 곱한 값을 더해준 것이 모멘텀이다.
결국 원래 빼주는 값에 관성계수 * 전 모멘텀을 더해준다.
관성계수는 보통 0.9 정도로 사용한다고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 44] feature engineering(2)]]></title>
            <link>https://velog.io/@im_ngooh/Day-44-feature-engineering2</link>
            <guid>https://velog.io/@im_ngooh/Day-44-feature-engineering2</guid>
            <pubDate>Mon, 14 Nov 2022 15:36:16 GMT</pubDate>
            <description><![CDATA[<p>22.11.14.
지난 주에 이어 feature engineering에 대해 배우고 있다.</p>
<hr>
<hr>
<h1 id="0701">0701</h1>
<h2 id="변수-선택feature-selection">변수 선택(Feature selection)</h2>
<ul>
<li>데이터에 존재하는 feature들 중 가치가 높은 feature를 선택하고 그렇지 않은 feature를 버리는 과정.<h3 id="분산-기반-선택">분산 기반 선택</h3>
</li>
<li>feature가 대부분 다 같은 값으로 이루어져 있거나 모두 다른 값이라면, 해당 feature는 예측에 도움이 되지 않을 확률이 높다.</li>
<li>따라서 머신러닝 모델에서 해당 feature를 제거한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/35b0dcfc-6940-4613-9986-41f843926cb9/image.png" alt=""></li>
</ul>
<pre><code class="language-python">non_col_list = []

for col in train.select_dtypes(include = &#39;O&#39;).columns:
    if train[col].value_counts(1)[0] * 100 &gt;= 90:
        non_col_list.append(col)

print(non_col_list)</code></pre>
<p>범주형 변수 중, 특정 범주가 90퍼센트 이상을 차지하는 변수들을 확인하였다.
해당 변수들은 예측에 도움이 되지 않을 확률이 높으므로 피쳐에서 제거하면 될 것 같다.</p>
<h3 id="상관관계-기반-선택">상관관계 기반 선택</h3>
<ul>
<li>어떤 feature 들 사이에 지나치게 높은 상관관계가 있다면, 둘 중 하나만 채택하고, 하나는 버린다. 이를 통해 과적합을 막을 수 있다.</li>
</ul>
<h3 id="feauture-importance">feauture importance</h3>
<ul>
<li>model을 학습한 후 .feature_importances를 이용해 피쳐 중요도를 볼 수 있다. 이는 각 feature가 해당 모델에서 결과 도출에 얼마나 기여했는지를 나타낸다.</li>
<li>그러나, 이는 모델과 난수마다 다르며, 절대적인 지표가 아니다.</li>
</ul>
<h1 id="0702">0702</h1>
<h2 id="왜도와-첨도-살펴보기">왜도와 첨도 살펴보기</h2>
<ul>
<li>왜도(skew)
.skew()로 살펴본다. 음수면 분포가 오른쪽으로, 양수면 왼쪽으로 치우쳐져 있다.</li>
<li>첨도(kurt, kurtosis)
.kurt()로 살펴본다. 0이면 정규분포, 0보다 크면 정규분포보다 뾰족한 분포이다.(Fisher의 정의)</li>
</ul>
<p>왜도와 첨도를 살펴보고, 분포의 그래프도 그려본다. 이를 토대로 어떻게 데이터를 사용할지 EDA를 진행한다.</p>
<p>왜도가 큰 값의 경우 로그 변환을 해주기도 한다.</p>
<h2 id="결측치">결측치</h2>
<ul>
<li><p>.isnull()을 사용한다. sum() 혹은 mean()으로 비율을 살펴볼 수 있다.</p>
<pre><code class="language-python">df = df.drop(columns = isna_mean[isna_mean &gt;= 0.80].index)</code></pre>
<p>결측치의 비율이 80퍼센트 이상인 피쳐들을 삭제하였다.</p>
</li>
<li><p>결측치를 채워주기 위해서는 fillna를 사용한다.
다양한 값으로 결측치를 채울 수 있고, 선택은 개인의 몫이다.
수치형변수냐, 범주형 변수냐에 따라서도 달라질 수 있다.</p>
</li>
</ul>
<p>실습에서 최빈값으로 채워보기도 진행했다.</p>
<pre><code class="language-python">df[fill_mode] = df[fill_mode].fillna(df[fill_mode].describe().loc[&#39;top&#39;])
# 또는
df[fill_mode].fillna(df[fill_mode].mode().loc[0])</code></pre>
<p>최빈값은 .mode로 판다스에서 구할 수 있다.</p>
<pre><code class="language-python">df[feature_num] = df[feature_num].fillna(df[feature_num].median())
df[feature_num].isnull().sum().sum()</code></pre>
<p>이런 식으로 fillna를 사용하기도 했다.
fillna의 인자에 str, 수치 뿐 아니라 dictionary나 Series를 넣을 수 있었다. (함수는 X)</p>
<h2 id="데이터-타입-바꾸기">데이터 타입 바꾸기</h2>
<ul>
<li>데이터의 타입이 수치형 변수더라도, 범주형 변수와 같이 동작하는 변수들이 있다.
nunique가 적은 수치형변수들이 그러하다. 사실상 ordinal encoding 되어있다고 생각할 수 있다.
해당 변수들은 범주형 변수로 바꾸어 one hot encoding 해주는 것이 더 효율적일 수 있다.<pre><code>num_col = df.select_dtypes(include = &#39;number&#39;).columns
df[num_col].nunique()[df[num_col].nunique() &lt; 15].index.tolist()</code></pre>와 같은 코드로 수치형 변수 중 범주형 변수로 변환시킬 변수들을 골랐다.
그 후 <code>.astype(str)</code>을 통해 범주형 변수로 변경해주었다.</li>
</ul>
<hr>
<h2 id="기타">기타</h2>
<ul>
<li><p>만약 기술통계값을 살펴봤는데, 수치형 데이터의 범위가 0~3의 정수 처럼 개수가 적다면 이는 수치형데이터보다는 범주형 데이터에 가깝다. 이럴때에는 nunique 값으로 추가적인 확인이 필요하다.</p>
</li>
<li><p>히스토그램은 수치 데이터의 분포를 확인하기 위해 그려본다. 막대가 이산적이라면 수치데이터가 아니라 범주형 데이터임도 확인할 수 있다. 수치데이터의 경우 분포 확인, 왜도와 첨도의 대략적인 파악을 통해 데이터가 너무 한쪽에 치우쳐져 있지는 않은지 확인한다.</p>
</li>
<li><blockquote>
<p>전처리를 한다면 학습과 예측에 도움이 될만한 피쳐엔지니어링 기법이 무엇이 있을지 고민</p>
</blockquote>
</li>
<li><p>이상치를 어떻게 처리해줘야할지?</p>
</li>
<li><blockquote>
<p>이상치를 평군이나 중앙값 등으로 대체하면 데이터에 왜곡이 될 수 있으니 주의가 필요하다. 차라리 상황에 따라서는 최댓값이나 최솟값 등으로 대체하는게 낫다.</p>
</blockquote>
</li>
<li><blockquote>
<p>현실 세계에서 풀어야할 문제 중에는 이상치를 탐지하는 문제도 있다. 이상치가 특별한 의미를 가지고 있다거나.</p>
</blockquote>
</li>
<li><p>희소값 : 범주형 데이터 중에서 빈도수가 적은 것.
One hot encoding시 희소값이 너무 많다면 연산에 시간이 오래걸릴 수도 있고, 과대적합이 발생할 수 있다. 따라서 희소한 값이라면 결측치 처리하거나 ‘기타’와 같이 묶어준다.</p>
</li>
<li><p>스케일링
트리계열모델에서는 스케일링이 필요없다. 그런데 로그를 취해 정규분포 형태를 띄게 해주는 것은 더 나은 성능을 내기도 한다.
스케일링은 회귀에 있어 아주 중요하다.</p>
</li>
<li><p>로그 트랜스포메이션
로그 트랜스포메이션을 먼저 한 후 스케일링해야 표준정규분포와 같은 형태가 된다.
왜 데이터를 정규분포 형태로 만들어주면 머신러닝이나 딥러닝에서 더 나은 성능을 낼까? 
분포의 중심(평균) 부분에 일반적으로 더 많은 데이터가 존재하기 때문에라고 생각함
데이터가 너무 한쪽에 몰려있거나 치우쳐져 있을 때보다 고르게 분포되어 있다면 데이터의 특성을 더 고르게 학습할 수 있습니다. (강사님 답)
정의역에 음수가 있다면, 최솟값의 절댓값 + 1 만큼을 더한 후 로그를 씌워준다.
다시 돌리기 위해서는 지수함수를 씌운 후 해당 만큼을 빼준다.
그러니까 log1p(x – 최솟값) 한 후 expm1(결과값) + 최솟값 하면 된다.</p>
</li>
<li><p>이산화(범주화)
Cut과 qcut. Cut은 절대평가 qcut은 상대평가.
RFM 분석 기법에서도 종종 사용되는 방법으로 비즈니스 분석에서 다룰 예정.
Recency, frequency, monetary =&gt; 고객이 얼마나 최근에, 자주, 많이 구매했는지를 분석할 때 사용
연속된 수치 데이터를 구간화. =&gt; 머신러닝 알고리즘에 힌트를 줄 수도 있다
트리모델의 경우 너무 잘게 데이터를 나누지 않아 일반화에 도움이 될 수도 있다
나누는 기준이 중요한데, EDA를 통해 어떻게 나누는 것이 예측에 도움이 될지 확인, 나누는 기준에 따라 모델의 성능에 영향을 주게 된다
오히려 잘못나누면 모델의 성능이 떨어질 수도 있다</p>
</li>
<li><p>인코딩
pandas에서는 .cat.codes, ordianl, get_dummies, one-hot
범주형 데이터 =&gt; 수치형 데이터(0~N숫자로 바꿔준다면 Ordinal, 해당되는 것만 1로 만들어준다면 One-Hot)
LabelEncoder, OrdinalEncoder 의 입력값의 차이?
LabelEncoder 입력이 1차원 y 값, OrdinalEncoder  입력이 2차원 X값</p>
</li>
<li><p>OndHotEncoder
handle_unknown = &#39;ignore&#39; 를 넣어주면, 변환 중에 알 수 없는 범주가 발생하면 이 기능에 대한 결과 원-핫 인코딩 열은 모두 0이 됩니다. 역변환에서 알 수 없는 범주는 없음으로 표시됩니다
그러니까 test를 인코딩하려는데, train에서 fit 할때에는 없던 범주가 있다면 오류가 나고, 우리의 목표는 이런건 다 결측치로 처리해버리는 거고, 그러려면 handle_unknown = ‘ignore’로 해주어야 한다! 
업데이트된 버전의 infrequent_if_exist는 fit에(train에) 없던 범주에 대해 자동으로 기타처리를 해준다!
원핫인코딩 하고 난 후에는 train, test 피처의 수가 같은지 꼭! 확인</p>
</li>
<li><p>전처리, EDA, 시각화
까먹지 않게 계속 실습하려고 노력하자. 노력!</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 40, 41] feature engineering]]></title>
            <link>https://velog.io/@im_ngooh/Day-39-40-feature-engingeering</link>
            <guid>https://velog.io/@im_ngooh/Day-39-40-feature-engingeering</guid>
            <pubDate>Sun, 13 Nov 2022 10:40:00 GMT</pubDate>
            <description><![CDATA[<p>22.11.08. ~ 22.11.09.
피쳐 엔지니어링에 대해 배웠다.
상당히 다양한 피쳐 엔지니어링 방법이 존재한다.
잘 익혀두고 적재적소에 활용하면 좋겠다!</p>
<hr>
<p>내용들은 멋쟁이사자처럼 AI SCHOOL 7기 박조은강사님(오늘코드)의 자료를 참고하였습니다.</p>
<hr>
<h1 id="데이터-분석의-과정">데이터 분석의 과정</h1>
<p>데이터 분석에 정해진 과정과 순서는 없다. 그러나 대부분의 경우 
데이터 수집 -&gt; 데이터 전처리 -&gt; 탐색적 데이터 분석(EDA) -&gt; 피쳐 엔지니어링 -&gt; 머신러닝 모델에 적용
의 과정을 거친다.</p>
<p>위 과정들은 서로 엄밀하게 구분된 영역도 아니며, 진행하다보면 얼마든지 순서가 뒤바뀌어 일어날 수 있는 과정이다.</p>
<p>그러나 내가 지금 하고 있는 일을 체계화하여 살펴보기 위해 해당 과정들을 나누어 진행해보면 좋다.</p>
<p>머신러닝의 전반적인 과정들을 살짝 체험했으니, 이 날부터는 피쳐 엔지니어링에 대해 공부해보았다.</p>
<h1 id="feature-engineering">feature engineering</h1>
<ul>
<li>데이터에 대한 지식을 바탕으로 feature를 생성, 변경, 삭제하는 등의 조작을 통하여 사용하기 더 유용한 형태로 바꾸는 것.</li>
<li>데이터의 전처리와 EDA를 통해 피쳐에 대한 기본적인 탐색을 진행한 후, 이를 토대로 진행한다.</li>
</ul>
<p>피쳐엔지니어링을 위한 EDA를 진행할 때 파악해야할 사항 몇가지를 살펴보자면, </p>
<ul>
<li><p>피쳐엔지니어링을 진행할 때에는 특히 피쳐의 자료형(수치형, 범주형)이 중요하다. 자료형을 보는 방법은</p>
<pre><code class="language-python">df.info()
df.select_dtypes(include = np.number)
df.select_dtypes(include = &#39;object&#39;)</code></pre>
<p>위 방법들이 존재한다.</p>
</li>
<li><p>결측치 탐색 역시 중요하다. 결측치는 nan으로 들어가있을 수도 있으나, 공백, &#39;-&#39;, 0 등 다양한 형태로 포함되어있을 수 있다. 따라서 자료의 도수분포를 살펴보거나 히스토그램을 살펴보는 등 다양한 방법으로 결측치를 탐색할 필요가 있다.</p>
</li>
<li><p>이상치를 탐색하고 판단하는 것 역시 중요하다. IQR등을 이용해 값의 범위에 따라 이상치를 찾을 수도 있고, 시각화를 통해 그래프를 이용하여 찾을 수도 있다. 이상치는 데이터의 해석과 모델의 학습을 방해하므로 제거하거나 대체해주는 것이 필요하다.</p>
</li>
<li><p>희소값에 대한 처리 역시 필요하다. 범주형 변수에 대해 희소값이 존재하는 경우, 이는 데이터의 경향을 파악하기 어렵게 만들어 해석을 어렵게하고 머신러닝의 성능을 낮출 수 있다. 인코딩을 진행할 때에도 오랜 계산시간과 많은 컴퓨팅 성능을 요구하기도 한다. 따라서 희소값들의 경우 &#39;기타&#39;와 같이 묶어주거나, 결측치 처리해주기도 한다.</p>
</li>
</ul>
<p>그럼 피쳐 엔지니어링에 대해 하나씩 살펴보자.</p>
<h2 id="feature-selelction-특성-선택">Feature selelction (특성 선택)</h2>
<ul>
<li>해당 분야의 전문 지식, 피쳐의 중요도 등에 따라 사용할 피쳐를 선택하는 것.</li>
<li>중요하지 않은 피쳐가 머신러닝의 성능에 악영향을 미치는 것을 방지하기 위해 사용한다.</li>
<li>EDA를 통해 이를 선택하는 것도 중요하지만, 직접 모델에 추가하고 제거해보면서 검증해보는 방법도 필요하다.</li>
</ul>
<h2 id="feature-extraction-특성-추출">Feature extraction (특성 추출)</h2>
<ul>
<li>피쳐들의 조합으로 새로운 피쳐를 생성하는 것.</li>
<li>PCA(주성분 분석)과 같은 기법이 이에 해당한다고 한다.</li>
<li>피쳐들을 통해 새로운 특성(피쳐)을 추출해본다고 생각할 수 있다.</li>
</ul>
<h2 id="transform-변형-파생변수-만들기">Transform (변형, 파생변수 만들기)</h2>
<ul>
<li>기존의 존재하는 변수의 성질을 이용해 새로운 변수를 생성하는 것</li>
<li>새로운 피쳐를 생성하는 것이 특징을 더 잘 드러내는 경우가 존재한다.</li>
<li>반면, 파생변수를 만들어 사용하였을때 머신러닝 모델의 성능이 오히려 떨어지는 경우도 많다.</li>
</ul>
<h3 id="polynomial-expansionpower-transform">Polynomial Expansion(power transform)</h3>
<ul>
<li>주어진 다항식의 차수 값에 기반하여 파생변수를 생성하는 방법
예를 들어, [a,b]에 대해 최대 차수가 2차수로 주어지면 1, a, b, aa, ab, bb를 만든다.</li>
<li>머신러닝 모델은 label에 대해서 설명력이 높은 한두가지 feature에 기반할때보다 여러가지 feature에 기반할 때 성능이 더 뛰어나기 때문에 ‘변수를 뻥튀기 시켜준다’라는 측면에서 유용할때가 있다. 소수의 feature에 기반하게 되면 과대적합이 일어날 확률이 높아지므로!</li>
<li>Uniform 한 값은 어딘가는 많고 어딘가는 적은 그런 특징이 없기에, 구분되는 특징이 부족할 수 있는데, power transform 등을 통해 값을 제곱을 해주거나 하면 특징이 더 구분되어 보일 수 있다!</li>
<li>scikit-learn에서<pre><code class="language-python"># preprocessing - PolynomialFeatures
from sklearn.preprocessing import PolynomialFeatures
</code></pre>
</li>
</ul>
<p>poly = PolynomialFeatures(degree = 2)
house_poly = poly.fit_transform(train[[&#39;MSSubClass&#39;, &#39;LotArea&#39;]])</p>
<p>pd.DataFrame(house_poly, columns = poly.get_feature_names_out())</p>
<blockquote>
<blockquote>
<blockquote>
</blockquote>
<pre><code>1    MSSubClass    LotArea    MSSubClass^2    MSSubClass LotArea    LotArea^2</code></pre><p>0    1.00    60.00    8,450.00    3,600.00    507,000.00    71,402,500.00
1    1.00    20.00    9,600.00    400.00    192,000.00    92,160,000.00
2    1.00    60.00    11,250.00    3,600.00    675,000.00    126,562,500.00
3    1.00    70.00    9,550.00    4,900.00    668,500.00    91,202,500.00
4    1.00    60.00    14,260.00    3,600.00    855,600.00    203,347,600.00
...    ...    ...    ...    ...    ...    ..</p>
</blockquote>
</blockquote>
<pre><code>

## Scaling (범위 변환)
- 범수의 분포가 편향되어 있을 경우나 이상치가 많이 존재하는 경우 등, 변수를 활용하기 어려울 때 변수의 범위를 변환해주는 것
- 여러 피쳐들의 범위가 서로 다를때엔 피쳐끼리의 비교가 어렵고, 모델에 학습시킬때에 중요도가 다르게 판단될 수도 있다. 스케일링은 이러한 문제를 해결할 수 있다.
- 피쳐 스케일링이 잘 되어 있다면, 머신러닝 모델의 성능은 상승하며, 경사하강법, KNN, clustering과 같은 거리 기반 알고리즘에서 더 빨리 작동한다.
- 일부 스케일링의 경우 이상치의 영향을 줄여주기도 한다.
- 그런데, 트리 기반 모델의 경우(결정트리, 랜덤포레스트) 데이터의 절대적인 크기보다 상대적인 크기가 중요하게 작용하기 때문에 피쳐 스케일링이 따로 필요하지 않다. 

### Standardization, Normalization (Z-score)
- 평균을 0으로, 표준편차를 1로 만들어주는 스케일링 기법
- `(X - X.mean()) / X.std()`
- 변수가 왜곡된 분포를 가지고 있거나, 이상치를 가지고 있다면 예측력을 손상시킬 수 있다는 단점이 있다.

+ 사이킷 런에서 사용하기
feature engineering에서 사용할 대부분의 사이킷런 기능들은 sklearn.preprocessing에 존재한다.
또한, 대부분 fit을 한 후 transform 을 진행하는 방식으로 사용하며, fit은 분포나 기술통계값을 파악하는 등의 역할, transform은 계산을 통해 실제 피쳐엔지니어링을 진행해주는 역할을 한다.
대부분 인자에 Series가 아닌 DataFrame 형을 요구한다.
그리고 이때 주의할 점은, **fit은 train set에 대해서만 진행한다**는 점이다! test set에는 fit 시키지 않고 transform 만 진행한다.

```python
from sklearn.preprocessin import StandardScaler

ss = StandardScaler()
ss.fit(train[[feature]]).transform(train[[feature]])

# 또는
# ss.fit_transform(train[[feature]])</code></pre><h3 id="min-max-scaling">Min-Max Scaling</h3>
<ul>
<li>변수의 최솟값을 0으로, 최댓값을 1로 만들어 주는 스케일링 기법</li>
<li><code>(X - X.min()) / (X.max() - X.min())</code></li>
<li>표준화와 마찬가지로, 왜곡된 분포 혹은 이상치가 있는 변수의 예측력을 손상시킬 수 있다.<pre><code class="language-python">from sklearn.preprocessing import MinMaxScaler
</code></pre>
</li>
</ul>
<p>ms = MinMaxScaler()
train[[&#39;SalePrice_mm&#39;]] = ms.fit(train[[&#39;SalePrice&#39;]]).transform(train[[&#39;SalePrice&#39;]])</p>
<pre><code>
### Robust Scaling
- 표준화와 유사한 방식이지만, 평균이 아닌 중간값과 표준편차가 아닌 IQR에 따라 분포를 조정해준다.
- 중간값을 빼주고  IQR 값으로 나눠준다. -&gt; 중간값이 0이 된다.
- `(X - X.median()) / (IQR)`
- IQR은 3분위수 - 1분위수를 의미한다.
- 해당 스케일링 방법은, 평균이 아닌 중간값을 사용하므로, 이상치에 강건하다는 장점이 존재한다!
```python
from sklearn.preprocessing import RobustScaler

rs = RobustScaler()
train[[&#39;SalePrice_rs&#39;]] = rs.fit_transform(train[[&#39;SalePrice&#39;]])</code></pre><p>사이킷런으로 위 스케일링들을 진행한 경우, .inverse_transform을 통해 원래 값으로 복원할 수 있다.</p>
<ul>
<li>위 세가지의 스케일링을 진행하여도, 변수의 분포 형태는 변하지 않는다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/745c4c49-b81c-41d7-9c30-a757d070f386/image.png" alt="">
위 그림은 원래 변수, Standard Scaling 해준 변수, minmax scaling 해준 변수, robust scaling 해준 변수의 histogram을 나타낸 것이다. 값의 크기에 차이는 있지만, 스케일링을 진행해주어도 변수가 가지고 있는 확률 분포는 달라지지 않음을 알 수 있다.</li>
</ul>
<p>확률 분포를 달라지게 하기 위해서는, log transform 을 진행해야 한다.</p>
<h3 id="log-transform">log transform</h3>
<ul>
<li>변수에 로그를 씌워줌으로써 분포를 변경하는 방법</li>
<li>로그를 씌워주면, 왜곡되고 치우쳐져 있는 분포가 좀 더 고르게 정규분포에 가까워지는 효과가 있다. (로그함수의 그래프를 보면, x 값이 클수록 기울기가 작아진다. 즉, 로그를 씌우면 작은 x에 대한 변화는 더욱 커지고, 큰 x에 대한 변화는 작아지는 효과가 있다.)</li>
<li>변수의 분포가 고르게 될 수록, 예측력은 상승한다고 할 수 있다.</li>
<li>대부분의 예측은 확률적으로 분포의 중앙 근처에서 일어날 것이기 때문! 변수의 분포가 왼쪽으로 치우쳐져있다면, 가운데 부분은 많이 학습되지 않은 상태일거고, 따라서 모델의 예측력은 하락한다 생각할 수 있다.</li>
</ul>
<p>0602 실습에서!</p>
<ul>
<li>실습에서, log1p를 통해 label 변수를 log transform 하고, 모델 학습 및 예측을 진행하였다. 그리고 그 예측값을 expm1으로 원래 분포의 값으로 변환시켜 최종 예측값을 구했다.</li>
<li>log1p란 1을 더한 후 로그를 취해준 값(로그를 취한 값이 음의 무한대로 가는 것을 방지), expm1은 지수함수를 취한 후 1을 빼주는 것을 의미한다.</li>
<li>log transform을 진행한 후 standardization을 한다면, 변수의 분포를 표준정규분포에 가깝게 만들어줄 수 있다.</li>
</ul>
<h2 id="binning-범주화">Binning (범주화)</h2>
<ul>
<li>수치형 변수를 범주형 변수로 변환하여 주는 것</li>
<li>즉, 수치형 변수를 일정 기준으로 나누어 그룹화 해준다고 할 수 있다.</li>
<li>이를 잘 활용한다면 유사한 예측 강도를 가진 속성들을 그룹화하여 모델의 성능을 개선하는데 도움이 될 수 있다. 또한 수치형 변수의 과대적합을 방지할 수 있다.</li>
</ul>
<h3 id="equal-width-binning-cut">equal width binning (cut)</h3>
<ul>
<li><p>수치형 변수를 동일한 길이의 N개의 bins로 나눈다.</p>
</li>
<li><p>예시로는 절대평가, 히스토그램 등이 있다.</p>
</li>
<li><p>편향된 분포에 대해 민감하다는 단점이 있다.</p>
<pre><code class="language-python">pd.cut(train[&#39;SalePrice&#39;], bins = 4, labels = [1,2,3,4])</code></pre>
<p>pd.cut의 인자로는 구간을 나누어줄 개수인 bins가 들어간다.</p>
<h3 id="equal-frequency-binning-qcut">equal frequency binning (qcut)</h3>
</li>
<li><p>수치형 변수를 동일한 관측값의 수를 가지는 N개의 bins로 나눈다.</p>
</li>
<li><p>예시로는 상대평가가 있다.</p>
</li>
<li><p>알고리즘의 성능을 높이는 데 도움이 될 수 있으나, 오히려 방해가 될 수도 있다.</p>
<pre><code class="language-python">pd.qcut(train[&#39;SalePrice&#39;], q=4, labels = [1,2,3,4])</code></pre>
<p>pd.qcut의 인자로는 구간을 나누어줄 개수인 q가 들어간다.</p>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/f80ddaa7-d84d-41e4-a760-327d7278358c/image.png" alt=""></p>
</li>
</ul>
<h2 id="dummy-숫자화-encoding">Dummy (숫자화, encoding)</h2>
<ul>
<li>범주형 변수를 수치형 변수로 변환해주는 것</li>
<li>데이터 시각화 또는 머신러닝 모델을 사용할때 범주형 변수를 사용하지 못하는 경우가 존재한다. 이럴때에는 인코딩을 해주어야 한다.</li>
</ul>
<h3 id="ordinal-encoding">Ordinal Encoding</h3>
<ul>
<li>범주형 변수의 고유값들을 임의의 숫자로 바꿔준다.</li>
<li>이때 기본적으로는 0부터 1씩 증가하는 정수로 지정한다.</li>
<li>이러한 표현방식으로 인해, 그 값이 크고 작음이 있는 순서형 변수일 경우 괜찮지만, 그렇지 않은 명목형 변수에 대해서는 오해를 불러일으킬 수 있다.</li>
<li>pandas에서는 category형 변수의 .cat.codes로 사용할 수 있다.<pre><code class="language-python">train[&#39;MSZoning&#39;].astype(&#39;category&#39;).cat.codes</code></pre>
</li>
<li>scikit-learn에서는 <pre><code class="language-python"># preprocessing - ordinal encoder
from sklearn.preprocessing import OrdinalEncoder
</code></pre>
</li>
</ul>
<p>oe = OrdinalEncoder()
train[[&#39;MSZoning_ohe&#39;]] = oe.fit_transform(train[[&#39;MSZoning&#39;]])
display(train[[&#39;MSZoning&#39;,&#39;MSZoning_ohe&#39;]].sample(6))
oe.categories_</p>
<pre><code>ordinal encoder를 선언한 후, fit시키고 transform 시켜주면 된다.
역시 주의할 점은 인자로 DataFrame 형태를 주어야한다는 점.
그리고 fit은 train set에만 진행하고 train은 transform 만 진행해야한다는 점.

공식문서 예시는 이렇다.
```python
from sklearn.preprocessing import OrdinalEncoder
enc = OrdinalEncoder()
X = [[&#39;male&#39;, &#39;from US&#39;, &#39;uses Safari&#39;], 
     [&#39;female&#39;, &#39;from Europe&#39;, &#39;uses Firefox&#39;]]
enc.fit(X)
print(enc.transform([[&#39;female&#39;, &#39;from US&#39;, &#39;uses Safari&#39;]]))
print(enc.categories_)
&gt;&gt;&gt;
[[0. 1. 1.]]
[array([&#39;female&#39;, &#39;male&#39;], dtype=object), array([&#39;from Europe&#39;, &#39;from US&#39;], dtype=object), array([&#39;uses Firefox&#39;, &#39;uses Safari&#39;], dtype=object)]</code></pre><h3 id="one-hot-encoding">One-Hot Encoding</h3>
<ul>
<li>범주형 변수의 고유값들을 모두 하나의 피쳐로 만든 후, 그 값일 bool(0 또는 1)로 표현한다.</li>
<li>피쳐의 모든 정보를 유지한다는 장점이 있으나, 너무 많은 고유값이 있으면 너무 많은 피쳐를 만들어 계산이 오래걸리고, 컴퓨팅 자원이 많이 필요하다.</li>
<li>pandas에서는 pd.get_dummies()를 사용한다.<pre><code class="language-python">pd.get_dummies(train[&#39;MSZoning&#39;])</code></pre>
</li>
<li>scikit-learn에서는<pre><code class="language-python"># preprocessing - OneHotEncoder
from sklearn.preprocessing import OneHotEncoder
</code></pre>
</li>
</ul>
<p>ohe = OneHotEncoder()
ohe_out = ohe.fit_transform(train[[&#39;MSZoning&#39;]]).toarray()
display(pd.DataFrame(ohe_out, columns = ohe.get_feature_names_out()).head())
ohe.categories_</p>
<pre><code>OneHotEncoder는 좀 복잡하다. 차근차근히 살펴보면, 
먼저 OneHotEncoder를 호출 및 선언 해주었고, fit_transform 해주었다.
이때 중요한 점은 ohe를 통해 transform 한 결과는 DataFrame이 아니라 scipy의 matrix 객체라는 것이다. 따라서 결과를 확인하기 위해서는 .toarray()를 해주어야 한다.
또한, 우리가 원하는 데이터프레임 형식으로 보기 위해서는 transform 결과 만들어진 피쳐들의 리스트를 컬럼으로 주어야 하는데, 이는 ohe.get_feature_names_out()으로 가져올 수 있다.

공식문서 예시는 이렇다.
```python
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
X = [[&#39;male&#39;, &#39;from US&#39;, &#39;uses Safari&#39;],
     [&#39;female&#39;, &#39;from Europe&#39;, &#39;uses Firefox&#39;]]
enc.fit(X)
enc_out = enc.transform([[&#39;female&#39;, &#39;from US&#39;, &#39;uses Safari&#39;],
               [&#39;male&#39;, &#39;from Europe&#39;, &#39;uses Safari&#39;]]).toarray()
print(enc_out)
print(enc.get_feature_names_out())
pd.DataFrame(enc_out, columns=enc.get_feature_names_out())
&gt;&gt;&gt;
[[1. 0. 0. 1. 0. 1.]
 [0. 1. 1. 0. 0. 1.]]
[&#39;x0_female&#39; &#39;x0_male&#39; &#39;x1_from Europe&#39; &#39;x1_from US&#39; &#39;x2_uses Firefox&#39;
 &#39;x2_uses Safari&#39;]
     x0_female    x0_male    x1_from Europe    x1_from US    x2_uses Firefox    x2_uses Safari
0    1.00    0.00    0.00    1.00    0.00    1.00
1    0.00    1.00    1.00    0.00    0.00    1.00</code></pre><ul>
<li><p>사이킷런과 판다스의 비교
단순히 적용하는 것은 판다스가 훨씬 간단하다. 하지만 사이킷런의 장점은 test set과 train set의 피쳐를 모두 맞춰줘야하는 복잡한 과정을 신경쓰지 않아도 되게 해준다는 것이다.
전에 인코딩을 진행할때, train 과 test에 있는 고유값들이 다르므로 피쳐가 달라지는게 문제가 된다고 했었다. 그래서 전에는 train set에서 2번 이상 나오는 고유값들만 남겨두고, 나머지는 기타로 처리했고, test set에서도 같은 기준으로 전처리해주었다.(train set 기준) 그 후 인코딩 해주었었는데, 아주 복잡했다.
scikit learn의 인코더를 사용하면 그런 문제가 해결된다. train set에만 fit을 진행하기 때문이다! 따라서 test set에 transform을 적용할때, train 에는 없는 고유값이 나오면 인코딩되지 않고 결측치처리가 되고, train에만 있는 고유값이 존재해도 test에 feature로 만들어진다.</p>
<h1 id="기타">기타</h1>
</li>
<li><p>실수에 다양한 계산을 취할 때, 소수를 저장하는데에 있어 메모리의 한계가 존재해 소수점 아래 일부 자리들은 버려지게 되므로 정확한 값이 아니라 오차가 나올 수 있다. 따라서 정수로 변환하여 사용하거나, 반올림을 적절히 활용하여야 한다. <a href="https://www.youtube.com/watch?v=ZQDsWySjY6g&amp;ab_channel=%EC%96%84%ED%8C%8D%ED%95%9C%EC%BD%94%EB%94%A9%EC%82%AC%EC%A0%84">참고</a></p>
</li>
<li><p>neg_mean_root_square
label에 log를 씌운 후 모델 학습 및 예측을 진행한 실습에서, cross validation을 진행할때 scoring을 neg_mean_root_square로 진행했다. 평가 지표는 rmsle였다.
log가 이미 씌워져있으므로 rmse를 구하면 된다는 것은 이해가 되었지만, 앞에 -은 왜 붙었을까? 
R2, accuracy 등 다양한 평가지표의 경우 클 수록 좋은 값이다. 그러나 rmse, mse, mae 와 같은 오차형 평가지표의 경우 작을 수록 좋은 값이다. 이 평가지표들의 정렬기준을 클 수록 좋은 값으로 통일시키기 위해 오차의 앞에는 -를 붙여 클수록(절대값이 작을 수록) 좋은 모델인 것으로 판단하고자 이렇게 했을 거라 추측할 수 있다. 라고 강사님이 말해주셨다!</p>
</li>
<li><p>house price competition 의 평가 지표
Submissions are evaluated on Root-Mean-Squared-Error (RMSE) between the logarithm of the predicted value and the logarithm of the observed sales price. (Taking logs means that errors in predicting expensive houses and cheap houses will affect the result equally.) 라고 나와있다.
결국 RMSLE이다. log를 취하는 이유는, log를 취하면 상대적 오차를 구하는 것이기 때문에, 비싼 집이든 저렴한 집이든 공평하게 적용하기 위해서!</p>
</li>
<li><p>pandas 옵션 코드
봤던 것들인데 음 찾아보며 쓰자~
<code>pd.options.display.float_format = &#39;{:,.2f}&#39;.format</code>
<code>pd.set_option(&#39;display.max_columns&#39;, None)</code></p>
</li>
</ul>
<hr>
<p>뭔가 하긴 했는데... 실습 하면서 다시 공부해봐야 익숙해질 듯 하다. 다시 열심히 해보자!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 39] Kaggle - bike sharing (1)]]></title>
            <link>https://velog.io/@im_ngooh/Day-39-Kaggle-bike-sharing-1</link>
            <guid>https://velog.io/@im_ngooh/Day-39-Kaggle-bike-sharing-1</guid>
            <pubDate>Mon, 07 Nov 2022 16:31:40 GMT</pubDate>
            <description><![CDATA[<p>22.11.07.
먼저 kaggle titanic 데이터를 GridSearch와 RandomizedSearch까지 마무리 했다.
그 후, bike sharing 데이터를 통해 회귀 예측을 해보기 위한 과정을 시작했다.</p>
<hr>
<h1 id="cross-validation">Cross validation</h1>
<ul>
<li>GridsearchCV
지정된 조합만 보기 때문에 해당 그리드를 벗어나는 곳에 좋은 성능을 내는 하이퍼파라미터가 있다면 찾지 못하는 단점이 있다.</li>
<li>RandomizedSearchCV<br>랜덤한 값을 넣고 하이퍼파라미터를 찾습니다. 처음에는 범위를 넓게 잡고 그 중 좋은 성능을 내는 쪽으로 범위를 좁혀가며 사용. 조합이 최적의 조합이라는 보장이 없다는 단점이 있다.
n_iter만큼의 estimators * cv만큼의 fold 학습</li>
</ul>
<ul>
<li><p>결과 attribute
Best_estimator_ : 어떤 분류기가 가장 좋은 성능을 내는지 알려준다.
Best_score_ : 가장 좋은 성능을 낸 점수를 알려준다.
Cv_results_ : (cross validation의) 전체 report를 출력해준다. 어떤 조각이 어떤 성능을 냈는지를 알려준다. </p>
</li>
<li><p>hold-out validation과의 차이
hold-out validation? 하나의 test-set을 만들어 검증하는 것. 평상시에 하듯 데이터를 train set과 test set으로 나누는  것!
hold-out-validation 은 한번만 나눠서 학습하고 검증하기 때문에 빠르다는 장점이 있다. 하지만 신뢰가 떨어진다는 단점이 있다.  hold-out-validation 은 당장 비즈니스에 적용해야 하는 문제에 빠르게 검증해보고 적용해 보기에 좋다고 한다!</p>
</li>
</ul>
<h1 id="eda">EDA</h1>
<ul>
<li>Kaggle에서 데이터를 다운받고, 데이터를 EDA하는 과정을 거쳤다.</li>
<li>데이터 설명을 잘 읽어보며 어떤 컬럼이 있고, 어떤 형태이며 어떤 의미를 가지는지 파악한다.</li>
<li>데이터를 불러와서 EDA를 진행한다.</li>
</ul>
<p>EDA 과정 중</p>
<ul>
<li>결측치를 isnull()이나 info()로 파악한다고 끝이 아니다. 지난번 당뇨병 데이터셋에서 봤듯이 결측치가 0으로 들어가 있을 수도 있다.</li>
<li>이런 이유 뿐 아니라, 당연히 데이터를 전반적으로 파악하고 의미있거나 특이한 점을 찾기 위해 describe()를 살펴본다.</li>
<li><strong>전체 수치형 변수의 histogram 그려보기</strong> 도 꼭 진행하자! 맨날 까먹지 말고!</li>
<li>이번 실습에서는 각 피쳐들의 scatterplot을 그려 변수들 사이의 대략적인 관계도 파악했었다.</li>
</ul>
<p>전처리 과정 중</p>
<ul>
<li>train set과 test set에 같은 전처리를 해줘야 함을 잊지 말자.</li>
<li>train에 한 전처리는 test에도!</li>
<li>encoding 등을 진행할때, test set을 활용하면 data leakage라고 하여 부정행위 처리되는 경진대회가 많다.</li>
<li>꼭 그렇지 않더라도, train set을 기준으로 전처리 하는 습관을 들이자!</li>
<li>train과 test의 더미변수가 달라질 것 같다면 &#39;기타&#39;처리 해주는 스킬!</li>
</ul>
<p>이상치 및 결측치 처리</p>
<ul>
<li>이상치인지, 입력 및 수집 과정 중 발생한 Error data인지 잘 판단해야한다.</li>
<li>체감온도가 12.2로 전부 측정된 날이 하루 있었다.
그래프를 통해 알 수 있었다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/277e6f99-45a1-497f-8a97-55569e5fc2cc/image.png" alt=""></li>
</ul>
<p>그래프를 잘 그려보고 잘 파악하자. 이런 경우 오류 데이터라고 파악할 수 있겠다.</p>
<ul>
<li>결측치... 제거를 할 수도, 대체를 할수도 있겠다. 일단 이번 실습에서는 0으로 되어있는 결측치들을 그대로 놔두었다.</li>
<li>이상치... 도 마찬가지! ㅎ...</li>
<li>결측치와 이상치의 처리가 가장 많이 생각해야하는 부분 아닐까..? 좀 더 고민을 해보자.</li>
</ul>
<h2 id="의문">의문</h2>
<h3 id="풍속에-따른-대여-수">풍속에 따른 대여 수</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/05acb05f-36be-460c-b27f-9a941b341966/image.png" alt=""></p>
<p>windspeed에 따른 대여 횟수의 scatterplot이다. 당연히 바람이 세게 불면 자전거를 빌리는 사람이 적을 것이라고 생각했고, 그래프를 보면, 바람이 세질수록, 대여 횟수의 최댓값이 작아지는 것은 확연하게 확인할 수 있다.</p>
<p>그러나, 점 하나하나가 데이터임을 명심하고 살펴보면, 풍속이 느리지만 자전거의 대여 횟수가 적은 데이터도 매우 많이 존재한다. 상관관계가 우리가 생각하던 대로 나오지 않은 것.
따라서 regplot을 그려보면 다음과 같은 형태다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/8f423a9c-9759-44e2-aab9-5ca66769ba82/image.png" alt=""></p>
<p>혹시 0으로 표시되어있는 결측치 때문인가 하여 결측치를 제거하고도 그려보았다.</p>
<pre><code class="language-python">wind_test = train.copy()
wind_test = wind_test.drop(wind_test[wind_test[&#39;windspeed&#39;] == 0].index)
sns.regplot(data = wind_test, x=&#39;windspeed&#39;, y=&#39;count&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/56f1b7ef-449e-46c6-82d9-2ba9882b9c3e/image.png" alt=""></p>
<p>그래도 같다. 우리가 생각하던 경향과는 완전히 다른 추세선을 보이고 있다. 맨 위의 값들만 있으면 모르겠는데, 그 밑의 값들이 많이 존재하여 회귀선이 우리 생각과 다르게 나온다.
지금 우리가 사용하고 있는 RandomForestRegressor가 선형회귀 모델을 제작한다면, 저 regplot의 라인의 기울기가 windspeed에 대한 기울기(계수)가 되는 것 아닌가? 그렇다면 오히려 windspeed는 피쳐에서 제외하는게 맞는 것 아닌가? 아 너무 헷갈린다. 모르겠다.</p>
<p>그래서 feature에서 windspeed만 빼고 돌려봤다. 그리고 제출까지 해보았다.
0.002점 좋아진다.. 흠...</p>
<p>! 근데 지금 생각해보면, 결국 그래프가 저렇게 나왔다는 건, 바람이 세게 불면 사람들이 적게 빌리는 것은 맞지만, 바람이 적게 분다고 많이 빌리지도 않는다는 것!
바람이 세게 불면 대여가 줄어들기야 하겠지만, 그렇다고 해서 바람의 세기와 대여횟수 사이엔 상관관계가 없다는 것! 실제로 windspeed와 count 사이의 pearson 상관계수를 구해보면, 0.101369라는 작은 값이 나온다. 
내가 생각했던 가설과 다르다고 해서 그냥 의미 없는 고민을 한 거구나! 데이터를 그대로 보지 않고 그냥 내 생각과 다르다고 이게 잘못되었다고 생각한건가? 그래프를 보던 상관계수를 보던 바람세기와 대여횟수의 관계는 바람이 셀수록 대여가 주는 것이 아니다! 내 상식과 내 마음대로 데이터를 곡해해서 해석하지 말아야겠다. </p>
<p>결론은 저걸 받아들이고, feature로 사용할지 안할지를 잘 선택하면 되겠다!
그럼 차라리 지난번에 한번 했던 것 처럼, 풍속이 몇 이상인지 아닌지를 0과 1로 구분해주는 컬럼을 만드는 건?</p>
<h3 id="날씨에-따른-대여-수">날씨에 따른 대여 수</h3>
<p>날씨에 따른 대여 수를 살펴보았다.</p>
<pre><code class="language-python">sns.barplot(data= train, x=&#39;weather&#39;, y=&#39;count&#39;,ci=None)</code></pre>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/bf149372-ba0c-43c9-9156-86073fc1d867/image.png" alt=""></p>
<p>1~4로 갈수록 날씨가 좋지 않은 것인데, 날씨가 폭우 또는 폭설을 의미하는 4일때가 3일때보다 평균 대여수가 많다.
그래서 날씨가 4인 날을 살펴봤더니, 딱 하루, 그것도 딱 한시간이다.
따라서 평균 대여수가 날씨가 3인 날보다 더 많은 것이라고 예측해볼 수 있다.</p>
<p>그러면 여기서 남는 의문은, 과연 이 날씨가 4일때의 데이터를, 학습에 사용하는것이 맞는가..? 라는 의문이 남는다. 잘못된 일반화와 학습이 진행되는 건 아닐까..!</p>
<p>결론은 나지 않았지만, 지금 생각하기엔 ordinal encoding으로 되어있기에, 1~3까지의 경향이 충분히 반영된다면 4일때의 데이터를 빼고 학습시켜도 되지 않을까? 잘은 모르겠다..</p>
<h2 id="특이했던-점">특이했던 점</h2>
<h3 id="월에-따른-대여-수">월에 따른 대여 수</h3>
<p>월별 대여수의 그래프를 살펴보았다.</p>
<pre><code class="language-python">sns.barplot(data = train, x=&#39;month&#39;, y=&#39;count&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/d7dccd25-e086-4a9d-9ca7-aed48b3084b4/image.png" alt=""></p>
<p>나름 의미있는 데이터인것 같아 보인다.</p>
<p>그러나, 년도에 따라 색상이 나누어지게 하여 살펴보았다.</p>
<pre><code class="language-python">sns.barplot(data = train, x=&#39;month&#39;, y=&#39;count&#39;, hue =&#39;year&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/32c2659b-68d1-41eb-9525-5d3f5d04f80f/image.png" alt=""></p>
<p>년도에 따라서 월별 대여수가 너무 차이가 많이 난다. 2012년이 2011년에 비해 확연히 많다. 심지어는 2011년의 12월 데이터와 2012년의 1월 데이터가 유사하다.</p>
<p>즉, 같은 달인데에도 연도에 따라 값이 차이가 많이 나기 때문에 오히려 성능을 저하시킬 수 있다. 따라서 피쳐에서 제외해주는 것이 좋다.</p>
<p>월별 경향은 분명히 존재하는 것 같으니, 이를 사용하고 싶다면 연-월 이라는 피쳐를 만들어 사용하는 방법도 있겠다. 약간 태블로에서의 불연속형 월과 연속형 월의 차이같은 느낌!</p>
<h3 id="day">Day</h3>
<p>Day를 살펴보면, train 데이터에는 1일부터 19일까지, test 데이터에는 20일부터 의 데이터만 존재한다. 따라서 day를 피쳐로 사용해 학습을 해봤자 그다지 도움이 되지 않는다는 것을 알 수 있고, 피쳐에서 제외해준다.
그리고 이는 train 과 test set을 day를 기준으로 나누었음을 짐작할 수 있게 해준다!</p>
<p>나는 사실 day는 뭐 크게 영향이 없을 것 같아 피쳐에서 제외했고, month는 season과 어느정도 겹치는 부분 아닌가 해서 제외했는데.. 우연히 제거해야하는 것들을 제거한 셈..!</p>
<h1 id="회귀-평가-지표">회귀 평가 지표</h1>
<p>오늘의 가장 어려웠던 것..!</p>
<h3 id="mae">MAE</h3>
<pre><code class="language-python">abs(y_train - y_valid_pred).mean()

from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_train, y_valid_pred)</code></pre>
<ul>
<li>실제값 - 예측값의 절댓값의 평균</li>
<li>절대값을 취하기 때문에 가장 직관적임</li>
<li>단위 자체가 기존 데이터와 동일하여 오차를 쉽게 파악할 수 있다.</li>
</ul>
<h3 id="mse">MSE</h3>
<pre><code class="language-python">((y_train - y_valid_pred) ** 2).mean()

from sklearn.metrics import mean_squared_error
mean_squared_error(y_train, y_valid_pred)</code></pre>
<ul>
<li>실제값 - 예측값의 제곱의 평균</li>
<li>제곱을 하기 때문에 특이치에 민감하다. (실제값과 예측값의 차이가 클수록 훨씬 증가한다.)</li>
</ul>
<h3 id="rmse">RMSE</h3>
<pre><code class="language-python">np.sqrt(((y_train - y_valid_pred) ** 2).mean())</code></pre>
<ul>
<li>실제값 - 예측값의 제곱의 평균에 루트를 씌운 값</li>
<li>실제 값과 유사한 단위로 다시 변환(다시 루트를 씌우므로)하여 MSE보다 해석이 더 쉽다.</li>
<li>MAE보다 특이치에 Robust(강건)</li>
</ul>
<h2 id="rmsle">RMSLE</h2>
<pre><code class="language-python">((np.log1p(y_train) - np.log1p(y_valid_pred)) ** 2).mean() ** 0.5
# log1p는 1을 더한 후 로그를 취해주는 함수

# 또는
from sklearn.metrics import mean_squared_log_error
rmsle = np.sqrt(mean_squared_log_error(y_train, y_valid_pred))
rmsle</code></pre>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/34df81ea-874b-44c7-a645-2af28b266225/image.png" alt=""></p>
<ul>
<li><p>RSME와 유사하나, 실제값과 예측값 대신 해당 값들에 1을 더하고 로그를 취한 값을 사용.</p>
</li>
<li><p>1을 더해주는 이유?</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/8/81/Logarithm_plots.png" width="300">

</li>
</ul>
<p>로그 함수의 그래프. x 가 1보다 작으면 로그 값이 음수가 나온다. 따라서 1을 더해서 로그를 씌운 결과가 음의 무한대로 발산하는 것을 방지!</p>
<ul>
<li>로그를 취해주는 이유는?
로그를 취해주면,
scaling 되는 효과가 있다. 값의 범위가 줄어든다.
분포가 정규분포에 가까운 형태가 된다.
한쪽으로 skewed 되있던 것이 좀 풀린다.</li>
</ul>
<p>라고 하는데, 솔직히 바로 납득은 안간다. 좀 더 써보고 공부해봐야 왜 로그를 씌워서 사용하는지 알 것 같다.</p>
<ul>
<li>RMSLE의 특징</li>
</ul>
<ol>
<li>이상치에 강건하다. 
log를 씌워 값의 scale을 줄여주었기 때문에 이상치에 비교적 강건하다.</li>
<li>상대적 오차를 측정해준다.
식을 생각해보면 log(실제값 + 1) - log(예측값 + 1)인데, 이는 log((실제값 + 1) / (예측값 + 1))이다. 따라서 RMSLE는 값이 변화한 비율을 나타내는 상대적 오차라고 볼 수 있다.</li>
<li>Underestimating에 대하여 더 가중치를 둔다.
음 log함수를 생각해보면, X값이 작아질수록 미분계수가 증가한다. 따라서 예측값이 실제값보다 작은 경우가, 큰 경우에 비해 log값의 차이가 크므로 RMSLE값이 크다.</li>
<li>작은 값들에 대해 크다.
3번에서의 내용을 일반화시키면 이렇게 볼 수 있지 않을까?
값이 작을수록 log 함수의 미분계수는 크다. 두 값의 차가 일정하다면, 두 값이 7,10일때보다 4,7일때 log 값의 차 역시 크다. 따라서 RMSLE는 작은 값들에 대해 더 크게 나타나는 효과를 가진다.</li>
</ol>
<p>4번은 사실 수업들으면서 헷갈렸던 부분이라 확실하지는 않다. 큰 값과 작은 값의 기준도 모호하긴 하고, 그래도 일단은 이런 식으로 알고 있으면 될 것 같다. </p>
<ul>
<li>오차의 가중치</li>
</ul>
<p>RMSLE는 log 기반이므로 수치가 작은 값들에 대해 더 크게 나타나는 효과를 가진다. 
약간 결은 다르지만, 
위에서 MSE는 잔차의 제곱으로 나타내므로, 실제값과 예측값의 차가 큰 값에 대해 더 크게 나타나는 효과를 가졌었다. RMSE도 당연히 마찬가지고!
MAE는 절댓값을 이용하므로 값의 크기에 따른 가중치가 없다!</p>
<p>RMSLE는 다른 오차들과는 다르게 상대적 오차((실제값 + 1) / (예측값 + 1)) 를 나타내기 때문에, 잔차(실제값 - 예측값)의 크기에 따른 가중치는 특정할 수 없겠다. 그것보다는 값들 자체의 절대적인 수치가 작을때 RMSLE가 커진다고 받아들였다.</p>
<ul>
<li>근데 이해가 안된 것
RMSLE 는 최솟값과 최댓값의 차이가 큰 값에 주로 사용됩니다. 라고 강사님이 말씀해주셨다. 으악 이건 또 왜지.. 좀 더 생각을 해봐야겠다.... 아마 상대적 오차를 나타내어주기 때문 아닐까! 다른 MSE 등을 이용하면 값이 너무 커질테니까!</li>
</ul>
<p>오늘의 결론 :</p>
<h1 id="진짜-eda가-중요하구나">진짜 EDA가 중요하구나...!</h1>
<p>EDA를 정말 꼼꼼히 잘 해보는게 머신러닝에 있어서 아주 중요함을 느낀 하루.</p>
<hr>
<p>기타</p>
<ul>
<li>미니프로젝트 진행할때, feature_importances도 안봤다... 이으이 정신 차리자! 잘 기억해보자!</li>
<li>경진대회의 점수를 올리기 위해 가장 중요한 것은 EDA이다! feature engineering은 오히려 할수록 점수가 떨어지는 경우도 많고 그렇다. 따라서 다양한 분야의 사람들, 도메인 전문가, 프로그래머, 데이터 사이언티스트 등이 모여 팀을 꾸린다.</li>
</ul>
<hr>
<p>더 공부해볼 것</p>
<ul>
<li>이론과 정리만 말고.. 진짜 실습의 필요성을 느끼고 있다!</li>
<li>이상치와 결측치의 판단 및 처리 기준을 끊임없이 고민해야할 듯.</li>
<li>어떤 평가기준을 언제 사용할지에 대한 고민 역시 필요!</li>
<li>회귀의 평가 지표는 더더 공부가 필요하다.</li>
<li>피쳐를 선택해주는 기준에 대한 고민 (feature importance 보기? 상관계수?)</li>
<li>다중공선성? 에 대한 내용을 좀 찾아보자. month와 season?</li>
<li>다들 Xgboost, lightGBM같은 모델들을 공부해서 미니프로젝트에 사용했더라...!</li>
<li>나도 배운것에만 의존해서 하려하지 말고, 스스로 더 찾아내고 공부하여 활용하고자 하는 마음가짐...! 을 가지자.</li>
<li>이 실습에서 더 해봐야 할것? 결측치 및 이상치 처리.. feauture engineering!</li>
</ul>
<hr>
<p>참고자료.</p>
<ul>
<li>해당 내용은 멋쟁이사자처럼 AI School 오늘코드 박조은 강사의 자료를 인용하였습니다.</li>
<li><a href="https://www.kaggle.com/competitions/bike-sharing-demand/submissions">https://www.kaggle.com/competitions/bike-sharing-demand/submissions</a></li>
<li><a href="https://ko.wikipedia.org/wiki/%EC%9E%90%EC%97%B0%EB%A1%9C%EA%B7%B8%EC%9D%98_%EB%B0%91">https://ko.wikipedia.org/wiki/%EC%9E%90%EC%97%B0%EB%A1%9C%EA%B7%B8%EC%9D%98_%EB%B0%91</a></li>
<li><a href="https://ahnjg.tistory.com/90">https://ahnjg.tistory.com/90</a></li>
<li><a href="https://steadiness-193.tistory.com/277">https://steadiness-193.tistory.com/277</a></li>
<li><a href="https://medium.com/analytics-vidhya/root-mean-square-log-error-rmse-vs-rmlse-935c6cc1802a">https://medium.com/analytics-vidhya/root-mean-square-log-error-rmse-vs-rmlse-935c6cc1802a</a></li>
</ul>
<hr>
<p>요즘 항상 너무 늦게 시작해서, 시간이 없다는 핑계로 자세히 공부 안하고 넘어가는데... 
반성하자!
회귀의 평가지표에 대한 자세한 내용을 더 공부해보고 싶다. 자료가 별로 없나..? 통계학 쪽인가..? 
결측치와 이상치 처리를 어떻게 해봐야 할 지도 생각해봐야겠고
어떤 피쳐를 사용하는게 옳은지에 대한 판단도 더 연습해봐야 한다!</p>
<p>그리고 아까도 생각했지만, 정리 하나하나에 매몰되지 말고, 오늘 수업 전체의 흐름을 생각하자!
다시 전체 한번 훑어보고 머릿속으로 정리하고 자자.</p>
<p>학교 원드라이브 계정이 변경된다고 그러더니, 동기화 오류가 났다. 필기 날라가진 않겠지?..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 38] Tableau 기초 (2)]]></title>
            <link>https://velog.io/@im_ngooh/Day-38-Tableau-%EA%B8%B0%EC%B4%88-2</link>
            <guid>https://velog.io/@im_ngooh/Day-38-Tableau-%EA%B8%B0%EC%B4%88-2</guid>
            <pubDate>Fri, 04 Nov 2022 16:26:33 GMT</pubDate>
            <description><![CDATA[<p>22.11.04
태블로 두번째 날.
확실히 태블로는 가볍게 들을 수 있다.
근데 하면서 계속 감탄하게 된다.
할 줄 알면 이런 저런 도움이 될 것 같다.</p>
<p>그리고 뭔가, 태블로는 정해진대로 딱딱보다는, 어떻게든 원하는 시각화만 해내면 된다 이런 느낌도 좀 들고,,?</p>
<hr>
<p>그래서 정리!</p>
<p>오늘은 뭘 배웠나..? 엄청 많이 배웠는데..?</p>
<p>배운거 중 사용법 위주만 대충 정리!
자세한 건 1104 필기 파일 보면서 다시 확인하자.</p>
<h1 id="영역-차트">영역 차트</h1>
<ul>
<li>라인 차트 아래가 색칠되어있는 차트. 마크에서 차트 종류를 영역차트로 변경해주면 된다.</li>
</ul>
<h1 id="그룹화">그룹화</h1>
<ul>
<li>오늘 많이 배운 것 중 하나!!!!!</li>
<li>특정 필드에 있는 값들을 그룹화하여 사용할 수 있다.</li>
<li>ex) 지역을 수도권과 비수도권으로 그룹화하여 보기
<img src="https://velog.velcdn.com/images/im_ngooh/post/f9c53358-8553-4adc-94e1-2926189c7102/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/215792cb-817f-40ef-b19d-2ad6c52a8f31/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/4738913e-60f9-4398-9fd9-5fec7a0624a2/image.png" alt=""></li>
</ul>
<h1 id="이중-축">이중 축</h1>
<ul>
<li>선반에서 드롭다운 메뉴를 통해 이중축 설정 가능</li>
<li>축 동기화 설정 및 머리글 표시 해제를 많이 사용</li>
<li>두 차트를 합쳐서 볼 때 많이 사용 (라인차트 위에 그림 추가 등)
<img src="https://velog.velcdn.com/images/im_ngooh/post/6717f226-b63a-472e-802c-204e4cecfa30/image.png" alt=""></li>
</ul>
<h1 id="필터">필터</h1>
<ul>
<li>필터를 추가하여 필터링 한다.</li>
<li>특정 항목만 선택 후, &#39;이 항목만 유지&#39;를 선택하여 필터링한다.</li>
<li>와일드카드를 이용해 필터링한다.</li>
<li>조건을 이용해 필터링 한다.</li>
<li>상위 및 하위 몇개 항목만 필터링한다.
등 다양한 필터링 가능
특히 날짜의 경우도 다양한 필터링 가능<h1 id="정렬">정렬</h1>
</li>
<li>툴바에서 오름차순 및 내림차순 설정</li>
<li>마크나 선반에서 드롭다운 메뉴 이용해 정렬</li>
<li>머리글에서 버튼 눈ㄹ러 정렬</li>
<li>차트에서 원하는 위치로 끌어놓아 정렬</li>
<li>필드를 만들어 수동으로 정렬도 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/fc5b856c-e50c-4fec-8139-dea15e845579/image.png" alt=""></p>
<h1 id="계층">계층</h1>
<ul>
<li>계층을 추가할 수 있다.</li>
<li><img src="https://velog.velcdn.com/images/im_ngooh/post/ce529e25-eef8-42af-a5c9-7ec847da6f02/image.png" alt="">
요런 식으로!
<img src="https://velog.velcdn.com/images/im_ngooh/post/bd1ec45a-35ac-4cbd-88d3-d43b7ba9ab46/image.png" alt="">
이렇게 앞에 + 표시가 있으면 계층이 있다는 것. 날짜는 저절로 계층화되어있다.</li>
<li>그냥 필드 두개를 합치듯이 끌어줘도 계층 형성이 가능하다.</li>
<li>계층 내에서 드래그를 통해 순서를 변경할 수 있다.</li>
</ul>
<h1 id="총계-추가">총계 추가</h1>
<ul>
<li>분석 탭에서 총계를 뷰로 드래그해 행방향, 열방향, 소계를 추가할 수 있다.</li>
<li>테이블의 총계 중 아무거나 누른 후, 마우스 우클릭 -&gt; 서식으로 들어가면 총계에 대한 서식 설정이 가능하다.</li>
<li>이름, 색상 등을 변경할 수 있다.</li>
<li>분석메뉴에서 총계를 테이블의 위와 왼쪽으로 불러오게 할 수도 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/17375708-2b2e-4e56-9ba2-0f39e6d4483a/image.png" alt=""></li>
</ul>
<h1 id="데이터-불러오기">데이터 불러오기</h1>
<ul>
<li>데이터 해석기, 유니온, 피벗, 필터, 숨기기 등 다양한 기능을 잘 사용한다.</li>
<li>시트와 필드의 이름도 잘 변경해주고, 자료형도 그렇다.</li>
<li>시트와 시트 연결시 관계를 형성해주는 것을 추천! (JOIN 보다는!)</li>
<li>데이터의 형태는 wide form 보다는 long form이 좋다.</li>
</ul>
<h1 id="파이-차트">파이 차트</h1>
<ul>
<li>파이차트 잘 만들 수 있다!</li>
<li>시각화를 할때 색상의 중요성을 항상 잊지 말자.</li>
<li>크기에 차이를 주기 위해 크기 편집을 통해 크기 범위를 바꾸어줄 수 있다.</li>
<li>레이블 추가를 통해 정보를 더 잘 살펴볼 수 있다.</li>
</ul>
<h1 id="맵-차트">맵 차트</h1>
<ul>
<li><p>태블로에서는 시도, 시군구까지 맵 형태로 표현이 가능하다. (지명을 통해 지리적 역할 추가)
혹은 위도, 경도만 있어도 가능하다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/7b09b73c-2df1-4a41-9bf3-7e335d920e7c/image.png" alt=""></p>
</li>
<li><p>지역 : 시도 기준으로 수도권, 영남 등으로 묶여있는 필드
맵으로 표현할 때 지리적역할 -&gt; 만들기 원본 -&gt; 시도 선택</p>
</li>
<li><blockquote>
<p>지리적 역할을 나타내는 것으로 만들어진 필드를 역시 지도에 표시할 수 있다.</p>
</blockquote>
</li>
<li><p>백그라운드 레이어 설정을 통해 원하는 부분만 표시 할 수 있다.</p>
</li>
<li><p>배경 맵 설정을 통해 거리맵, 위성사진 등 다양한 지도 표현 가능</p>
</li>
<li><p>마크에서 색상 및 레이블에 들어갈 수준 조절하여 다양한 차트 표시 가능</p>
</li>
</ul>
<h2 id="맵-차트---다중-마크-계층-지원">맵 차트 - 다중 마크 계층 지원</h2>
<ul>
<li>맵 차트는 다중 마크 계층이라는 것을 지원한다.</li>
<li>이를, 여러 계층을 가지는 도넛 차트를 만들기 위해 이용하기도 한다.</li>
<li>맵과는 관련이 없는 시각화를 하지만, 여러 계층으로 만들기 위해 맵 차트를 이용하는 것!</li>
</ul>
<p>방법</p>
<ul>
<li>기준 포인트 필드 추가(계산된 필드 이용, MAKEPOINT(0,0)) 그냥 아무 점이나 맵 차트에 표시하는 것</li>
<li>마크의 빈 공간에 더블클릭하여 min(1)을 추가, 크기로 지정</li>
<li>그 후 파이차트를 만든다.</li>
<li>도넛 차트를 위해 파이차트를 하나 더 추가하는데, 이때 원하는 필드를 맵 차트 위로 끌어와 &#39;계층추가&#39;가 나타나게 하여 거기로 드래그한다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/b9a271ac-fac6-422b-95db-3eab10da5de3/image.png" alt=""></li>
</ul>
<p>이렇게!
그렇게 해서 여러 계층을 가지는 도넛 차트를 만든다. 원래 1개밖에 안되는ㄴ데!
<img src="https://velog.velcdn.com/images/im_ngooh/post/129ca4b5-50e8-4b70-b754-0b7e55de0614/image.png" alt=""></p>
<h1 id="퀵-테이블-계산">퀵 테이블 계산</h1>
<ul>
<li>다양한 퀵 테이블 계산을 쉽게 잘 활용할 수 있다.</li>
<li>테이블 계산 편집을 통해 어떻게 계산을 진행할건지 (패널 아래로,  특정차원 등) 설정 가능하다. 꼭 필요!</li>
<li>누계</li>
<li>차이</li>
<li>순위</li>
<li>구성비율 등 다양하다.</li>
<li>퀵테이블계산으로 만들어진 걸 더블클릭하면 식을 볼 수 있다. 필드에 추가도 가능하고!</li>
<li>그런식으로 잘 활용하면 될듯</li>
</ul>
<h1 id="계산된-필드-만들기">계산된 필드 만들기</h1>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/d5ba58b7-3d54-44f8-a164-69b3dbe8c562/image.png" alt=""></p>
<ul>
<li><p>시도 이름 만들기</p>
<pre><code>IF ENDSWITH([시도],&#39;남도&#39;) OR ENDSWITH([시도],&#39;북도&#39;)
THEN LEFT([시도], 1) + MID([시도],3,1)
ELSE LEFT([시도],2)
END</code></pre><p><img src="https://velog.velcdn.com/images/im_ngooh/post/9e6f81e1-fab0-4768-800e-5c33c6511608/image.png" alt=""></p>
</li>
<li><p>수익 5천만원 이상인지
<img src="https://velog.velcdn.com/images/im_ngooh/post/13b947db-53b1-43ac-ae5f-e74415bb269e/image.png" alt="">
문자열보다는 숫자형과 bool의 연산이 더 빠르므로 이를 활용하자.</p>
</li>
<li><pre><code>{FIXED [시도] : MAX([시도별 확진자])} = [시도별 확진자]</code></pre><p>FIXED를 통해 해당 필드를 고정시키고 그 내에서만 함수를 적용.</p>
</li>
</ul>
<p>이렇게 만든 계산된 필드는 다양한 곳에 활용한다. 필터든, 마크든, 측정값으로 표시하든..</p>
<h1 id="매개-변수">매개 변수</h1>
<ul>
<li>음... 뭐라 표현해야 할까?</li>
<li>데이터를 선택해주기 위해 사용하는 값!</li>
<li>단독으로는 사용할 수 없다. 계산된 필드나 다른 무언가와 합쳐서 사용해야 함</li>
<li>매개변수 만들기 -&gt; 매개변수 표시 를 통해 사용한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/a0611ed1-2d87-4ea7-93da-649725b002f9/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/f97d760b-9d70-4097-9837-0e8d98b141a1/image.png" alt=""></p>
<p>위 두과정을 진행해 매출 단위를 조정할 수 있다.</p>
<p>오늘은 두개의 매개변수를 통해 (신규와 누적), (확진자수와 사망자수)를 선택하여 보게 할 수 있었다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/c823e72d-dc03-4f80-a424-3b9e71e4b422/image.png" alt="">
이렇게 매개변수를 만든다.
매개변수의 이름은 주로 p.으로 시작하고, 계산된 필드는 c. 으로 시작하게 만들어준다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/17f2ae22-dae4-46df-be2a-77525fb3dca7/image.png" alt="">
요렇게 만들었다.
그리고 매개변수 표시를 해준다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/78723930-2e61-4c2d-a53b-36414a286021/image.png" alt="">
그리고 단일 값 목록으로 표시하게 해주면 위의 사진처럼 매개변수를 통해 선택할 수 있다.</p>
<p>매개변수는 혼자 쓸 수 없으므로, 계산된 필드를 만들어줘야한다. (매개 변수는 계산, 필터 또는 참조선에서 상수 값으로 대체할 수 있는 숫자, 날짜 또는 문자열과 같은 통합 문서 변수입니다.)
따라서 이런 계산된 필드를 만들어준다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/c4d5e2b8-bdb7-40ec-9e2a-5ff293acb39c/image.png" alt=""></p>
<p>신규 누적 매개변수도 마찬가지로 만들어주고 표시해주고, 계산된 필드도 만들어준다!</p>
<pre><code>CASE [p. 신규 &lt;-&gt; 누적]
WHEN 0 THEN [c.확진 &lt;-&gt; 사망]
WHEN 1 THEN RUNNING_SUM([c.확진 &lt;-&gt; 사망])
END</code></pre><p>이렇게!</p>
<p>좀 이해가 된다. 잘 활용하면 좋겠다!</p>
<h1 id="사용자-지정-분할">사용자 지정 분할</h1>
<ul>
<li>필드를 분할하기 위해 사용자 지정 분할을 사용할 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/0f844430-7985-4bc6-8e12-59f133dcdd19/image.png" alt=""></p>
<ul>
<li>분할범위의 경우, 첫번째는 처음부터 몇 열을 가져올지, 마지막은 뒤에서부터!</li>
</ul>
<h1 id="인터랙티브-대시보드-대시보드---동작">인터랙티브 대시보드 (대시보드 - 동작)</h1>
<ul>
<li>대시보드의 동작을 통해 다양한 동작을 하게 만들어줄 수 있다.</li>
<li>오늘은 주로 필터, 매개변수와 함께 동작을 만들어주었다.</li>
<li>대시보드를 만들때, 바둑판식 말고 부동식을 선택할 수도 있다.</li>
<li>부동식은 띄워서 아무곳에나 개체를 표시하는 것!</li>
<li>부동식일때 레이아웃 패널에서 부동 순서 앞뒤 조절이 가능하다.</li>
</ul>
<p>오늘은 맵 차트를 인터랙티브하게 만들어주었다.
먼저 시트에서 각각 시도 범위의 매장수, 시군구범위의 매장수, 전체 매장의 위치를 표시한 맵 차트를 만들어주었다.</p>
<p>그 후 대시보드에서, 가로개체를 추가하고, 그 안에 다 넣는다.</p>
<p>그리고 대시보드 -&gt; 동작 -&gt; 동작 추가 -&gt; 필터!</p>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/8f446966-f0a6-465e-a922-1d5dd1f82e5c/image.png" alt="">
요렇게! 자세히 살펴보면 이해가 된다! 마찬가지로 시군구 -&gt; 매장 전체도 해준다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/a803ffa0-1b7b-412c-88ce-a8a638888b47/image.png" alt=""></p>
<p>선택을 해제 시 해당 차트가 날아가게 해주기 위해 제목 표시를 해제한다. 그러면 선택 없을때 세부 차트는 보이지 않을 정도의 사이즈가 된다.</p>
<p><a href="https://public.tableau.com/shared/B2KTTM88F?:display_count=n&amp;:origin=viz_share_link">https://public.tableau.com/shared/B2KTTM88F?:display_count=n&amp;:origin=viz_share_link</a></p>
<hr>
<p>오늘 실습한 것들</p>
<ul>
<li><a href="https://public.tableau.com/app/profile/.62031984/viz/_16675220059990/2?publish=yes">맵 차트 시각화</a></li>
<li><a href="https://public.tableau.com/app/profile/.62031984/viz/_16675240218880/3?publish=yes">이중축</a></li>
<li><a href="https://public.tableau.com/app/profile/.62031984/viz/2_16675260020290/1_1?publish=yes">다중 계층</a></li>
<li><a href="https://public.tableau.com/app/profile/.62031984/viz/22_11_04/sheet11?publish=yes">오늘 한거</a></li>
</ul>
<hr>
<p>더 들을 강의</p>
<ul>
<li>그룹과 계층 그리고 집합</li>
<li>테이블로 값 비교하기</li>
<li>퀵 테이블 계산</li>
<li>계산된 필드 만들기</li>
<li>결합된 축 만들기, 테이블 패널 셀</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 31] Tableau 기초]]></title>
            <link>https://velog.io/@im_ngooh/Day-31-Tableau-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@im_ngooh/Day-31-Tableau-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Thu, 03 Nov 2022 08:49:18 GMT</pubDate>
            <description><![CDATA[<p>22.10.28.
태블로 기초에 대해 배웠다. 강승일 강사님께!</p>
<p>22.11.03. 복습해보자!</p>
<p>태블로라는 툴 자체를 처음 봤는데, 첫인상은 되게 강력하다. 되게 직관적으로 원하는 시각화를 잘 진행할 수 있게 해주는 툴인 것 같다. 계산 같은 것도 쉽게 할 수 있고, 차트 모양같은건 뭐 말할것도 없고, 심지어 대시보드까지 만들 수 있고...</p>
<p>근데 수업 들으면서 실습한게 다 날아갔다. 아... </p>
<p>급히 복습하는거라 엉망진창이긴 한데...
나중에 써먹을때 더 공부해봐도 될 듯!</p>
<hr>
<h1 id="태블로란">태블로란</h1>
<ul>
<li>누구나 편하게 데이터를 분석하고 시각화를 진행할 수 있도록 만들어진 BI 툴.</li>
<li>사용법도 간단하며, 강력하다.</li>
<li>무료 버전인 태블로 퍼블릭과, 다양한 유료 버전이 존재한다.</li>
</ul>
<h1 id="태블로-데이터-연결">태블로 데이터 연결</h1>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/470c2395-0fba-4a67-83be-43e8b43594b0/image.png" alt=""></p>
<ul>
<li><p>엑셀, csv등 다양한 데이터를 연결할 수 있다.</p>
</li>
<li><p>엑셀을 연결할 때에는, 첫 행이 자동으로 필드의 이름이 된다.</p>
</li>
<li><p>데이터 해석기를 사용한다면, 포맷이 이상한 엑셀의 데이터도 읽어올 수 있다.</p>
</li>
<li><p>데이터를 연결 한 후, 숨김으로 사용 안할 필드를 숨길 수 있다.</p>
</li>
<li><p>또한, 필터를 통해 다양한 처리를 해줄 수 있다.</p>
</li>
<li><p>피벗을 통해 행을 열로 만들 수도 있다.</p>
</li>
<li><p>필드의 이름도 바꾸어줄 수 있다.</p>
</li>
<li><p>그런 다양한 기능을 사용해 데이터를 원하는 형태로 조작한 후 시트에서 시각화를 진행한다.</p>
</li>
<li><p>여러 테이블을 연결시켜줄 수도 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/531b3bce-7b14-47ce-9cf3-d2ed7e1d8297/image.png" alt="">
이렇게 유니온 할 수 있다.</p>
</li>
</ul>
<h1 id="태블로-자료형">태블로 자료형</h1>
<p>태블로는 데이터를 크게 두가지 타입으로 나눈다. 바로 측정값과 차원이다.</p>
<ul>
<li>측정값
연속적인 값, 수치 값, 초록색 필드, 단절이 없고 끊어지지 않는 무한대 범위, 뷰에 추가하면 축을 추가</li>
<li>차원
불연속적인 값, 개별적으로 구분, 파란색 필드, 유한한 범위, 뷰에 추가하면 머리를을 추가함</li>
</ul>
<p>여기서 뷰란, 그래프가 그려지는 영역을 의미한다.
축이란 우리가 생각하는 바로 그런 축, 머리글은 범주형 데이터에 대해 값을 나누어주는 축이라고 생각하면 되겠다.</p>
<ul>
<li><p>날짜 데이터의 경우, 측정값으로 볼 수도 있고 차원 값으로 볼 수도 있는데 어떤 값으로 보냐에 따라 시각화가 달라지게 된다. 마우스 오른쪽 버튼을 누른 채 행이나 열에 날짜를 끌어다놓으면 필드 놓기 대화상자가 표시되어 어떤 형식의 데이터로 놓을지 선택이 가능하다.</p>
</li>
<li><p>측정값의 경우, 마크에 추가되면 저절로 테이블 계산이 된 상태로 추가되게 된다. 기본 연산은 합계이고, 연산의 종류를 설정해줄 수 있다.</p>
</li>
<li><p>일반적으로 측정값은 숫자 형식이고, 액션하면 집계를 통해 차트를 만들고, 차원은 그 숫자들로 만들어진 차트를 어떻게 나눠서 볼 것인지를 결정한다.</p>
</li>
<li><p>연속형과 불연속형 필드를 자유롭게 변환할 수 있다. 각각 자료형별로 행, 열 등 어느 곳에 우선적으로 배치되는지가 미리 정해져 있다. 측정값은 집계되어 행으로, 차원은 열로 들어간다.</p>
</li>
<li><p>날짜 타입 같은 경우 연 분기 월 일 순으로 구체화하여 살펴볼 수도 있다.</p>
</li>
<li><p>불연속형 날짜는 정말 년이면 몇년, 월이면 몇월 등으로 나누어주고,</p>
</li>
<li><p>연속형 날짜는 월이라면 몇년 몇월 등으로 나누어준다.</p>
</li>
<li><p>숫자/문자 등도 변경이 가능하다.</p>
</li>
<li><p>특정 값을 없애기 위해서는 필터를 잘 활용하자.</p>
</li>
</ul>
<h1 id="계산된-필드-만들기">계산된 필드 만들기</h1>
<p>태블로에서는 계산된 필드 만들기라는 강력한 기능을 제공한다. 필드에 다양한 함수를 적용하여 계산한 값을 하나의 필드로 사용하고, 이를 시각화할 수 있는 것이다.
VizQL이라 하여, SQL함수와 같은 식을 필드에 지정하여 계산을 시행할 수 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/ba38094d-c8fa-4c3a-8c60-5cd6f2a46280/image.png" alt=""></p>
<p>계산된 필드는 다양한 방법으로 만들 수 있다.</p>
<ol>
<li>기본 계산 : 간단한 기본적 계싼, 집계 수준 혹은 기본 연산의 계산</li>
<li>LOD(세부수준식) : {FIXED [고객번호] : MIN[주문 일자]} 와 같은 식</li>
<li>테이블 계산 이용</li>
</ol>
<ul>
<li><p>퀵 테이블 계산을 사용한 필드를, ctrl을 누른 채로 테이블에 옮겨주면 해당 필드를 언제든지 추가하여 사용할 수 있다.</p>
</li>
<li><p>테이블 계산을 전체에 대해 진행하지 않고, 특정 차원이나 패널, 셀에 대해서만 진행하고 싶다면, 테이블 계산 편집에서 지정해줄 수 있다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/76b56aa4-d62c-435d-ad2f-c514fe2e8aae/image.png" alt=""></p>
</li>
<li><p>식을 쓸 때, 글자의 색상에 따라, 주황색은 필드, 함수는 파란색</p>
</li>
<li><p>//는 주석이다.</p>
</li>
<li><p><code>IF 날짜 = {MAX(날짜)} THEN DATETRUNC(&#39;month&#39;, [날짜]) END</code> : 최근 월 계산</p>
</li>
<li><p>데이터형 표시 그림에서 =이 있다는 건, 계산된 필드로 만들었다는 것!</p>
</li>
</ul>
<p>이렇게 계산된 필드를 만들어 차트 제목에도 사용할 수 있다. 요렇게!
<img src="https://velog.velcdn.com/images/im_ngooh/post/289ccda6-b527-4f85-99b2-ffb4f1ba8c83/image.png" alt=""></p>
<ul>
<li><p>최근 날짜를 파악하기 위해 f.최근일자 필드를 만들어준다.
[일자] = {MAX([일자])}  f.을 붙여준 이유는 필터로 사용할 필드임을 나타내는 것!</p>
</li>
<li><p>전일 대비 상승인지 하락인지 보합인지 파악하는 필드
IF [전일 대비 종가] &gt; 0 THEN &#39;Up&#39;
ELSEIF [전일 대비 종가] &lt; 0 THEN &#39;Down&#39;
ELSE &#39;-&#39; END</p>
</li>
</ul>
<h1 id="태블로-그래프-종류">태블로 그래프 종류</h1>
<p>태블로에서 표현 방식을 클릭하면(Ctrl + 1), 만들 수 있는 다양한 종류의 그래프가 나온다. 또한, 해당 그래프를 만들기 위해 어떤 데이터들이 필요한지까지 나온다. </p>
<ul>
<li><p>막대차트
가장 기본적이다. 
막대 차트를 만드는 이유?
각각의 변수별로 측정값을 한 개의 덩어리 막대차트로 만들 수 있어서
범주형 차원끼리 비교하기 쉬워서
순위를 비교하기 쉬워서
추세를 살펴보기 유용해서(특히 날짜에 대해!)
<img src="https://velog.velcdn.com/images/im_ngooh/post/be97e193-5cb5-4036-8197-7448feaf474c/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/f0c8cd94-e471-4a27-a879-f6435a8b37ea/image.png" alt=""></p>
</li>
<li><p>라인차트 만들기
날짜에 대해 그래프를 그릴때 라인 차트를 많이 사용한다.</p>
</li>
<li><p>맵 차트 만들기
위도와 경도가 존재하면 맵 차트를 만들 수 있다.
위도나 경도가 없더라도, 태블로에서는 지리적 역할을 부여할 수 있다!!!!
지명을 통해서 지리적 역할 추가 필요
지리적 역할 선택 -&gt; 경도와 위도가 자동으로 생성됨</p>
</li>
</ul>
<p>이를 통해 간단하게 지도 시각화를 진행할 수 있다.
한국 같은 경우 시군구까지 지리적역할 추가가 가능하다.
문자로 되어있는 국가, 지역, 시군구, 시도 필드를 기준으로 지리적역할로 표시하여 맵 차트에 표현하면 된다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/013f075d-3e17-435a-9e15-64abd471145e/image.png" alt=""></p>
<h1 id="그래프-설정">그래프 설정</h1>
<h3 id="마크">마크</h3>
<p>마크를 통해 특정 필드나 측정값의 색상, 크기, 레이블 등을 설정해줄 수 있다. 아주 쉽고 간편하다! 심지어 그래프의 종류도 바꾸어줄 수 있다.</p>
<h3 id="행과-열">행과 열</h3>
<ul>
<li>직관적이다. 행과 열 자리에 원하는 필드를 드래그해 추가하면 된다. 안쓸 것들은 밖으로 던져버리면 된다.</li>
</ul>
<h3 id="분석-패널">분석 패널</h3>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/0a44b780-64aa-4d39-b008-eaae92230ab6/image.png" alt="">
다양한 추가 분석을 위한 기능을 제공한다.</p>
<h3 id="이중-축">이중 축</h3>
<p>축을 여러개로 적용할 수 있다.
이중 축 : 제한된 공간에서 복수개의 값을 비교해서 볼 때 주로 사용한다.
누적 막대 차트(stacked bar chart)로 기본적으로 지정(색상 지정시) 세모옵션 -&gt; 정렬에서 정렬 기준 지정 가능
합계를 보기 위해 행에 하나 더 추가, 색상 지정 취소, 간트 차트로 변경 -&gt; 후 이중 축 추가!(행에 있는 것의 옵션 사용) -&gt; 서로 어긋난 축이 만들어짐. 축을 맞춰주려면? 축에서 마우스 오른쪽 버튼 -&gt; 축 동기화
축을 노출하기 싫다면? 축에서 머리글 표시 해제
굳이 이중축 없이 하고싶으면? 참조선 추가로 하면 됨! 이게 훨씬 간단.
축 편집을 통해 축에서 나타낼 범위도 설정하면 좋다.</p>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/e46706d6-3a20-4617-95c9-ade95c74634d/image.png" alt=""></p>
<h3 id="보기-설정맞춤-영역">보기 설정(맞춤 영역)</h3>
<p>맞춤영역을 전체보기로 변경하면 전체 fit에 맞추어 화면이 확대되어 보인다는 것!</p>
<h3 id="기타">기타</h3>
<ul>
<li>매출을 label 마크에 넣으면 합계 매출이 레이블로 나온다.</li>
<li>드랍다운메뉴(옵션)을 통해서 퀵 테이블 계산, 구성 비율 선택하여 비율 보기!</li>
<li>세모모양의 의미? 테이블 계산이 지정되어 있다. 더블클릭 해보면 계산식을 알 수 있다!</li>
<li>퀵 테이블 계산으로 만든 것을 사이드바에 던져주어서, 아예 하나의 필드로 만들고, 이름까지 지정할 수 있다.</li>
<li>색상 입히기? 어느 것을 기준으로 입힐지 결정해야함!</li>
<li>범주형의 경우엔 hue와 같은 역할이고, 수치형의 경우에는 그라데이션 형식으로 나오게 된다!</li>
</ul>
<h1 id="태블로-대시보드-만들기">태블로 대시보드 만들기</h1>
<ul>
<li>진행한 시각화들을 이용해 대시보드를 만들 수 있다.</li>
<li>대시보드의 크기, 레이아웃도 지정할 수 있다.</li>
<li>텍스트, 제목, 다운로드 버튼, 그래프 등 다양한 것이 들어갈 수 있다.</li>
<li>가로 및 세로 개체도 잘 활용하면 좋겠다.</li>
<li>계산을 위해 함수를 잘 활용해야 대시보드를 잘 만들 수 있겠다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_ngooh/post/8233c917-5f3e-4883-a786-8307b13621d3/image.png" alt="">
<img src="https://velog.velcdn.com/images/im_ngooh/post/e2f9bafa-1eba-45d7-9dc2-8e02a2b38f28/image.png" alt=""></p>
<ul>
<li>가장 최근 값만 표시하기 위해서?
LAST() = 0이라는 계산식을 통해 결과가 T/F인 필드를 하나 만든 후, 필터에다 참만 표시하도록 넣어주면 된다!</li>
</ul>
<h1 id="태블로-퍼블릭-업로드">태블로 퍼블릭 업로드</h1>
<p>업로드..!</p>
<hr>
<p>아주 날림으로 복습했다. ㅋㅋㅋㅋ
애초에 수업 들을 때에도 마음이 떠있어서 가볍게 들었는데, 정신도 없었고...
복습도 가볍게!
내일은 캡쳐 좀 하면서 필기해야겠다. 헷갈리네!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 34] kaggle - Titanic(2)]]></title>
            <link>https://velog.io/@im_ngooh/Day-34-kaggle-Titanic2</link>
            <guid>https://velog.io/@im_ngooh/Day-34-kaggle-Titanic2</guid>
            <pubDate>Wed, 02 Nov 2022 16:50:30 GMT</pubDate>
            <description><![CDATA[<p>22.11.02.
어제에 이어 캐글 타이타닉을 진행하며 kaggle 경진대회에 참여하는 법을 배웠다!
이 과정에서 머신러닝을 배웠다.
특히, pd.get_dummies()를 통해 인코딩하는 법, train set과 test set을 전처리 하는 법, 결측치를 대체하는 법에 대해서도 배웠으며, cross-validation에 대해 공부했다.</p>
<hr>
<h1 id="머신러닝을-위한-데이터-전처리">머신러닝을 위한 데이터 전처리</h1>
<h3 id="파생변수-만들기">파생변수 만들기</h3>
<ul>
<li>머신러닝에 사용할 feature를 파생변수로 만들어 준다.</li>
<li>이는 여러 수치형 변수 컬럼들을 계산하여 만든 값이 될 수도 있고, </li>
<li>범주형 변수 컬럼을 인코딩 하기 좋도록 범주를 정리해 준 것일 수도 있으며</li>
<li>간단한 바이너리 인코딩을 통해 범주형 변수를 수치형 변수로 바꾸어 준 것일 수도 있다.</li>
<li>전처리를 할 때, 도메인 전문가 등의 의견이나 실제 현업에서 어떻게 쓰이는지 조사를 하고 전처리 해야한다.</li>
</ul>
<p>머신러닝을 위해 데이터를 전처리 할 때, 주의해야 할 점이 있다.
바로, <strong>train set 과 test set에 동일한 전처리를 해주어야 한다</strong>는 점이다.
머신러닝을 진행할 때, train set과 test set의 feature의 종류와 개수는 당연히 동일해야한다. 따라서, 전처리를 진행할 때에 train과 test set에 대해 동일하게 진행해 주어야 한다는 것을 항상 유의하자!</p>
<p>실습에서는 이러한 파생변수들을 만들었다.</p>
<pre><code class="language-python">train[&#39;FamilySize&#39;] = train[&#39;Parch&#39;] + train[&#39;SibSp&#39;] + 1

test[&#39;FamilySize&#39;] = test[&#39;Parch&#39;] + test[&#39;SibSp&#39;] + 1</code></pre>
<p>동승한 부모 자식의 수, 형제의 수 컬럼을 이용해 가족의 수 피쳐를 만들었다.</p>
<pre><code class="language-python">train[&#39;Gender&#39;] = (train[&#39;Sex&#39;] == &#39;female&#39;)

test[&#39;Gender&#39;] = (test[&#39;Sex&#39;] == &#39;female&#39;)</code></pre>
<p>&#39;Gender&#39;라는 object type의 컬럼을, bool type을 가지도록 변환한 파생변수를 만들어주었다. 머신러닝에서는 object type 데이터를 사용할 수 없기에!</p>
<p>사실 뒤에서는, 이 Gender를 인코딩 하여 사용하기도 하였다.</p>
<pre><code class="language-python">train[&#39;Title&#39;] = train[&#39;Name&#39;].apply(lambda x : x.split(&#39;.&#39;)[0].split()[-1].strip())
test[&#39;Title&#39;] = test[&#39;Name&#39;].apply(lambda x : x.split(&#39;.&#39;)[0].split()[-1].strip())</code></pre>
<p>Name 피쳐에서, Mr, Miss 등의 호칭만 뽑아내어 새로운 피쳐를 만들어 주었다.
음... 성별과 연령을 동시에 파악할 수도 있는 지표일 것 같다! 그런데 이 피쳐는 좀 더 전처리가 필요하다. </p>
<p>test set에만 존재하는 호칭이 존재하기 때문이다...!
이렇게 파악해볼 수 있다.</p>
<pre><code class="language-python">set(test[&#39;Title&#39;].unique()) - set(train[&#39;Title&#39;].unique())
&gt;&gt;&gt;
{&#39;Dona&#39;}</code></pre>
<p>와 이걸 어떻게 set으로 바꿔서 차집합을 통해 파악해볼 생각을..! 진짜 짱이다.
잘 기억해두자 이런 방법.</p>
<p>그게 중요한게 아니라, test set에만 존재하는 호칭이 있는게, 왜? 뭐가 문제지?
인코딩을 진행할 것이기 때문에 문제가 된다.</p>
<h3 id="train과-test의-피쳐-맞춰주기">train과 test의 피쳐 맞춰주기</h3>
<p>이거! 이거 중요하다. </p>
<blockquote>
<p>일부 피처는 범주형 데이터이기에, 머신러닝 모델에서 사용하기 위해서는 인코딩을 진행해야 한다.
그리고 인코딩을 진행하였을 때에, train과 test에서 만들어진 feature의 종류와 수가 동일해야 한다. 그렇기 위해서는, 해당 범주형 데이터에 존재하는 범주들을 통일시켜야 한다. </p>
<p>결국, 범주형 변수에 들어있는 범주들이 train과 test set에서 동일해야 한다는 것이다. 동일하게 맞춰줘야 한다.</p>
</blockquote>
<p>후... 이걸 꼭 머릿속에 잘 넣고 다니자! <strong>train set과 test set에 존재하는 feature는 동일해야 한다!</strong> 따라서, 인코딩을 진행하려면, 안에 있는 범주들을 똑같이 맞춰줘야 한다!</p>
<p>그럼 어떻게 맞춰줘야하나? 여기서는, 호칭 피쳐에 대해, train set에서 여러 번 나오는 범주들을 골라내어, 그렇지 않고 몇 번만 나오는 범주들은 모두 &#39;기타&#39;로 만들어주었다.</p>
<p>음.. 좀 더 이해해보자.
실생활의 데이터를 분석할때, 예를 들어 미래를 예측한다면? 우리는 test set에 어떠한 데이터가 있는지 모른다. 아직 모르는 데이터를 예측하는 거니까!
결국, 머신러닝 모델에 사용하기 위해 데이터를 전처리 할때, 우리가 알고 있는 데이터는 train set 밖에 없다. 따라서, 모든 전처리는 train set을 기준으로 진행한다.</p>
<p>그런데 위와 같은 상황에서, train set의 호칭 피처에 존재하지 않는 범주가 test set에 존재할 수 있다. 그러한 test set을 그냥 인코딩한다면, train 과 test set의 피쳐의 종류와 개수는 달라져, 머신러닝 모델을 제대로 활용할 수 없을 것이다.
따라서, train set에서 기준을 잡아 전처리를 진행해준다. train set에서 여러 번 나오는 호칭들은 test set에도 여러번 나올 것이기도 하고, 모델에 영향을 끼칠 확률이 높으니 그대로 두겠고, 몇 번 나오지 않는 호칭들은 그냥 싸그리 &#39;기타&#39;로 묶어버린다.</p>
<p>그러면 test set을 같은 기준으로 전처리할 때, 자주 나오는 호칭들은 그대로 존재하겠고, train set에서 몇번 나오지 않았던 호칭들, 심지어는 train set에 아예 존재하지 않았던 호칭들까지 모두 &#39;기타&#39;라는 범주가 될 것이다.</p>
<p>이렇게 진행해줘야, 머신러닝을 할 때 오류를 방지할 수 있다. train set과 test set의 feature의 종류와 개수를 같게 맞춰준다! 기준은 train set으로!</p>
<p>실습은 다음과 같이 진행했다.</p>
<pre><code class="language-python"># 2개 이하의 경우 Etc로 묶어주기!
train_Title = train[&#39;Title&#39;].value_counts()
Not_etc = train_Title[train_Title &gt;= 3].index.tolist()
display(Not_etc)

train.loc[~train[&#39;Title&#39;].isin(Not_etc), &#39;TitleEtc&#39;] = &#39;Etc&#39;
train[[&#39;Title&#39;,&#39;TitleEtc&#39;]].sample(5)

test.loc[~test[&#39;Title&#39;].isin(Not_etc), &#39;TitleEtc&#39;] = &#39;Etc&#39;
test[[&#39;Title&#39;,&#39;TitleEtc&#39;]].sample(5)</code></pre>
<p>이렇게 하면 된다...! 잘 받아들이고, 기억하자.
set으로 변환해 test에만 존재하는 값이 없는지 다시 확인한다.</p>
<pre><code class="language-python">set(test[&#39;TitleEtc&#39;].unique()) - set(train[&#39;TitleEtc&#39;].unique())
&gt;&gt;&gt;
set()</code></pre>
<p>없다. 이렇게 하면 된다...!</p>
<p>위에서 실생활의 데이터를 처리할때 train set을 기준으로 처리한다 했었다. 그런데 사실 우리는 지금 kaggle에서 경진대회를 참가하고 있으므로, test set에 대해서도 알고 있고, test set과 train set의 유니크값을 합쳐서 전처리를 해주어도 된다.
그래도 어쨌든 기억해둘 것은, test set의 데이터를 모르고 있기 때문에, train set의 데이터를 기준으로 전처리를 진행한다!</p>
<p>위와 같은 과정을 진행한 이유를 강사님은 이렇게 설명하셨다.</p>
<blockquote>
<p>Train에만 등장하는 호칭은 학습을 해도 test에 없기 때문에 예측에 큰 도움이 되지 않는다. 또한, one=hot encoding을 진행할 것이기 때문에 train에만 등장하는 호칭을 피처로 만들어주게되면 피처의 개수가 늘어나는데 불필요한 피처가 생긴다. 불필요한 피처가 생기기도 하고 데이터의 크기도 커지기 때문에 학습에도 시간이 더 걸린다. 따라서 트레인에서 별로 등장하지 않는 호칭은 테스트에서도 별로 등장하지 않을 거라는 가정 하에 이를 기타로 빼준다. 너무 적게 등장하는 값을 피처로 만들었을 때, 해당 값에 대한 오버피팅 문제도 있을 수 있습니다. 
여기다가, 인코딩을 했을 때 피처가 달라지는 문제!</p>
</blockquote>
<p>음 Title의 범주들을 train set에서 2번보다 많이 나오는 것들만 골라준 이유는 다음과 같이 설명하셨다. 이거 잘 기억하면 좋을 듯.</p>
<blockquote>
<p>2개보다 큰 값만 가져오도록 했는데 2개보다 작은 값에 대해서만 예외처리를 하게 되면 앞으로 다른 train, test에 없는 값이 들어왔을 때 다시 전처리 해주어야 합니다. 예외에 추가가 필요합니다.</p>
</blockquote>
<h2 id="데이터-인코딩">데이터 인코딩</h2>
<ul>
<li>머신러닝 모델이 학습을 진행할 때 문자(object type data)는 인식을 하지 못하여 진행할 수 없다. 따라서 문자형 데이터들을 숫자로 바꿔주는 것이 필요하고, 그게 바로 인코딩이다.</li>
<li>인코딩의 종류로는 간단히 one-hot encoding과 ordinary encoding이 존재한다.</li>
<li>one-hot encoding은 각 범주 자체를 하나의 컬럼으로 만들어 범주형 데이터가 해당 범주에 속하면 1, 아니면 0으로 표현해주는 방식이다.</li>
<li>ordinary encoding은 범주형 변수에 대해, 각 범주들을 0,1,2와 같은 숫자로 표현해주는 방식이다. 이는 주로 순서가 있는 범주형 데이터(순위형 자료)에 대해 많이 사용한다. 명목형 자료에 대해 이 방식을 사용한다면, 의도치 않은 가중치가 부여되어 원하는 결과를 얻지 못할 수 있다.</li>
<li>인코딩은 주로 pandas의 pd.get_dummies()를 사용하거나, 사이킷런에서 encoder를 사용하여 진행한다. 오늘은 pd.get_dummies()를 배웠다.</li>
</ul>
<h4 id="pdget_dummies">pd.get_dummies()</h4>
<p><code>pd.get_dummies()</code>는 데이터를 one-hot encoding 시켜주는 판다스 함수이다.</p>
<p>이 함수의 대표적인 특징은, 인코딩 해야하는 범주형 변수를 자동으로 골라내어 인코딩 해준다는 점이다.
즉, 수치형 변수와 범주형 변수가 섞여있는 데이터프레임을 인자로 넣어줄 경우, 수치형 변수는 그대로 두고, 범주형 변수만 인코딩해 만든 데이터프레임을 반환한다.
게다가, 결측치가 있어도 인코딩을 진행할 수 있다.
인코딩을 진행할 범주형 변수에 결측치가 존재하면, 인코딩으로 만들어진 모든 컬럼의 값을 0으로 표현함으로써, 결측치 처리가 진행되게 된다.
만약 dummy_na = True로 하면, NaN 컬럼이 따로 생긴다.
따라서 매우 강력한 함수이다!</p>
<p>실습에서는 이렇게 사용했다.</p>
<pre><code class="language-python">X_train = pd.get_dummies(train[feature_names])
print(X_train.shape)
X_train.head(2)

X_test = pd.get_dummies(test[feature_names])
print(X_test.shape)
X_test.head(2)</code></pre>
<p>사용법도 아주 간단하다!</p>
<h4 id="인코딩을-위한-전처리">인코딩을 위한 전처리</h4>
<p>머신러닝을 진행할 때, train set과 test set의 feature의 종류와 개수는 당연히 동일해야한다. 그런데, 하나의 범주형 변수에 대해, train set과 test set에 존재하는 범주의 종류들이 다르다면? Encoding을 진행하면 피쳐의 종류와 개수가 달라지게 된다.
따라서, 인코딩을 진행하기 전 train set과 test set에 대해 전처리가 필요하다.</p>
<p>앞에서 설명했다. ### train과 test set의 피쳐 맞춰주기에서 설명한 내용을 사실 여기서 하려고 했던 것..!</p>
<p>여기서는 강사님의 말을 첨부하겠다.</p>
<blockquote>
<p>현실세계에서 pandas의 get_dummies를 사용한다면 train 따로 test 따로 만들어주겠죠. 왜냐하면 미래에 앞으로 어떤 데이터가 들어올지 모르기 때문입니다!
train과 test에 다른 값이 존재하면, 서로 다른 피처를 만들 수 있습니다.
그러나 보통 경진대회에서는 train,test set이 정해져 있습니다. 따라서 하나로 합쳐서 전처리하고 같은 피처를 만든 후, 다시 나누어주는 방법을 사용하기도 합니다!</p>
</blockquote>
<h2 id="결측치-대체">결측치 대체</h2>
<ul>
<li>결측치를 대체하는 방법에는 정답이 없다.</li>
<li>머신러닝을 위해 전처리를 할 때, 결측치를 어떻게 대체할지는 자유이다.</li>
<li>단지, 성능을 더 잘 낼 수 있는 값으로 대체하면 된다.</li>
<li>결측치 행 제거</li>
<li>결측치를 중앙값 등으로 대체</li>
<li>결측치를 보간법 등을 이용하여 대체 등의 방법이 존재한다.</li>
<li>예를 들어 나이의 경우, 그냥 중앙값으로 채울수도 있고, 여성과 남성 별 평균 나이를 구해 성별에 따른 나이의 평균으로 채울 수도 있고, 좌석의 종류에 따른 평균 나이로 채울수도 있고… 그 중 가장 적절한 방법을 찾아서 채우면 된다.</li>
<li>그리고 결측치를 채울 때, 오류도 막고 원래 값과의 비교도 위해 새로운 컬럼을 만들어서 채우는 것을 추천한다.</li>
<li>현실세계에서 분석하는 데이터에선 함부로 결측치를 채우는 일에 주의해야 한다!!!! 분석이 완전히 달라질 수 있다!!!!</li>
</ul>
<p>일단은 중앙값으로 채웠다.</p>
<pre><code class="language-python">train[&#39;Age_fill&#39;] = train[&#39;Age&#39;].fillna(train[&#39;Age&#39;].median())
test[&#39;Age_fill&#39;] = test[&#39;Age&#39;].fillna(test[&#39;Age&#39;].median())

train[&#39;Fare_fill&#39;] = train[&#39;Fare&#39;]
test[&#39;Fare_fill&#39;] = test[&#39;Fare&#39;].fillna(test[&#39;Fare&#39;].median())

train[&#39;Fare_fill&#39;].isnull().sum(), test[&#39;Fare_fill&#39;].isnull().sum()</code></pre>
<p>&#39;Fare&#39;의 경우, test set에만 결측치가 존재하나, train set에도 전처리를 진행해준다.</p>
<p>또한, fillna의 메소드를 이용하는 방법과, pandas의 interpolate를 사용하는 방법도 배웠다. 해당 방법들은 주로 시계열 데이터나 센서 데이터와 같이 앞 뒤의 데이터끼리 연관이 있는 경우 사용한다.</p>
<ul>
<li><p>fillna
method라는 매개변수에 다음과 같은 값이 들어갈 수 있다. <code>method : {&#39;backfill&#39;,&#39;bfill&#39;,&#39;pad&#39;,&#39;ffill&#39;,None}</code>
&#39;backfill&#39;과 &#39;bfill&#39;의 경우, <code>use next valid observation to fill gap</code> , 결측치 이후에 오는 값으로 결측치를 채워준다.
&#39;ffill&#39;,&#39;pad&#39;의 경우, <code>propagate last valid observation forward to next valid</code>, 결측치 이전에 오는 값으로 결측치를 채워준다.</p>
</li>
<li><p>interpolate (보간법)
<code>알려진 데이터 지점의 고립점 내에서 새로운 데이터 지점을 구성하는 방식</code>이 바로 보간법이다.
즉, 이전 및 이후 데이터들을 통해 결측치에 들어갈 데이터를 파악하여 채워준다.
간단히는 다음과 같이 사용한다.
<code>DataFrame.interpolate(method=&#39;linear&#39;, limit_direction=None)</code>
<code>method</code>에는 linear, polynomial, spline 등 다양한 값이 들어갈 수 있다.
linear를 사용하면 간단한 선형 관계식을 통해 이전 이후 데이터를 토대로 결측치 자리에 들어갈 데이터를 파악한다. (Ignore the index and treat the values as equally spaced. This is the only method supported on MultiIndexes.)
<code>limit_direction</code>의 경우, <code>{{‘forward’, ‘backward’, ‘both’}}</code>가 들어갈 수 있다. Consecutive NaNs will be filled in this direction. 해당 방향으로 진행하며 결측치가 채워지게 된다. 예를 들어 맨 앞에 결측치가 존재하면, limit_direction이 forward이면 채워지지 않는다. 우리는 주로 both를 사용한다.</p>
</li>
</ul>
<h3 id="기억하자">기억하자!</h3>
<ul>
<li>train set에 해준 전처리는 test set에도 동일하게 진행해줘야 한다.</li>
<li>train set과 test set의 feauture의 종류와 개수는 동일해야 한다.</li>
<li>test set의 데이터는 모르고 있기 때문에, train set의 데이터를 기준으로 전처리를 진행한다!</li>
</ul>
<hr>
<h1 id="모델-생성-및-학습-예측과-제출">모델 생성 및 학습, 예측과 제출</h1>
<h3 id="feature-label-나눠주기">feature, label 나눠주기</h3>
<ul>
<li>feature_names, label_name을 지정해주어 feature와 label을 정한다.<h3 id="train-test-set-만들기">Train, test set 만들기</h3>
</li>
<li>캐글 타이타닉 대회의 경우 애초에 train, test로 나누어져 있는 데이터를 제공한다.</li>
<li>여기서 우리가 전처리를 진행하였고, 사용할 feature와 label만 골라 머신러닝에 실제 사용할 train, test data를 만든다.</li>
<li>전처리를 마친 후, 이 과정에서 Encoding을 진행하면 편하다.</li>
<li>다음과 같이 진행했다.<pre><code class="language-python">X_train = pd.get_dummies(train[feature_names])
print(X_train.shape)
X_train.head(2)
</code></pre>
</li>
</ul>
<p>X_test = pd.get_dummies(test[feature_names])
print(X_test.shape)
X_test.head(2)</p>
<p>y_train = train[label_name]
y_train</p>
<pre><code>### 머신러닝 알고리즘 불러와 학습하기
- 다양한 알고리즘을 불러와, 모델을 fit 시킨다.
- 첫번째 실습 파일에서는 DecisionTreeClassifier를 사용했다.
성능은 랜덤포레스트가 더 좋지만, 그냥 빨리빨리 베이스라인 모델을 만들어보기 위해 사용했다. cross-validation을 진행할 건데 시간이 너무 오래걸리면 안되기도 하였고!
- 두번째 실습 파일에서는 RandomForestClassifier를 사용했다.
랜덤포레스트는, 의사결정나무 알고리즘의 단점을 보완한다. 오류가 하강적으로 전파되는 의사결정나무와 달리, 랜덤포레스트는 여러 트리를 만들어 종합한 결과를 사용하기 때문에, 오류값에 대해 비교적 강건하다. 일반화하여 사용하기도 좋다. 이는 배깅과 같은 앙상블 기법에 의한 효과이다.
- 이 과정에서 GridSearchCV나, RandomizedSearchCV를 사용해 하이퍼파라미터 최적화도 진행한다.
- Cross-validation을 통해 모델의 대략적인 성능도 파악해본다.
- 그냥 accuracy를 파악해볼 수도 있다.
- 모델의 성능이 안나오면 모델을 변경하거나, 피쳐 엔지니어링을 진행하는 등의 방법으로 최적화 시킨다.
- feature_importance 도 살펴보며 잘 활용한다!

### 예측하기
- fit 시킨 모델을 이용해 predict한다.
`y_predict = model.predict(X_test)`

### 제출 파일 만든 후 제출하기
- 제출 파일 양식을 불러오고, Survived 자리에 y_predict를 넣어준다.
- 해당 파일을 csv로 내보낸 후 캐글에 제출해, 점수를 본다!

이때 팁이라면, 파일 이름에 우리가 cross-validation 등으로 파악한 모델의 성능 점수를 넣어주어 캐글에서 test set에 대한 점수와 비교할 수 있다.

---

# cross_val....
이거. 진짜 모르겠더라! 아니 cross-validation의 개념은 알겠는데, 각 함수가 어떤 기능을 하는건지가 이해가 안 되었다.
그래서 열심히 공부를 한번 해봤다....
일단 간단한 개념 정리. 강사님이 해주신거!
- cross_validate : Evaluate metric(s) by cross-validation and also record fit/score times. 학습결과에 대한 점수와 시간이 나옵니다. 점수를 보고자 할 때는 편리하지만 지정한 metric에 의해서만 점수가 계산됩니다.
- cross_val_score : Evaluate a score by cross-validation. 각 valid set에 대한 점수가 나옵니다.
- cross_val_predict : Generate cross-validated estimates for each input data point. 예측 값이 그대로 나와서 직접 계산해 볼 수 있습니다. 직접 다양한 측정 공식으로 결과값을 비교해 볼 수 있습니다.

실습 코드는 다음과 같다.
```python
from sklearn.model_selection import cross_validate, cross_val_predict, cross_val_score

# cross_validate : 시간, 점수 계산 시간, 점수가 나옵니다.
pd.DataFrame(cross_validate(model, X_train, y_train))

# cross_val_score : 조각 별 스코어
cross_val_score(model, X_train, y_train)</code></pre><p>각 함수들의 사용법에 대해서는 익숙해졌다! 각 함수들이 반환하는 값도 무엇인지 알았다.</p>
<p>그런데 여기서부터 의문이 생겼다.</p>
<pre><code class="language-python"># cross_val_predict : 예측 결과 값, 그 결과로 직접 다양한 방법으로 정확도 계산이 가능하다.
y_valid_pred = cross_val_predict(model, X_train, y_train)
y_valid_pred[:5]

valid_accuracy = (y_train == y_valid_pred).mean()
valid_accuracy</code></pre>
<p>cross_val_predict를 사용하여 전체 데이터의 예측값을 알아내고, 이 예측값을 이용해 모델의 정확도를 파악했다...!
이게 대체 뭐지...?</p>
<hr>
<h4 id="의문-1">의문 1</h4>
<p><strong>*cross_val_predict의 결과 예측값은, 어떤 모델을 사용하여 예측한 값인가? *</strong></p>
<p>cross_val_predict는 어쨌든 cross-validation의 일종이다.</p>
<p>cross-validation은 </p>
<blockquote>
<p>train data 전체를 여러개의 fold로 나눈다.
그리고 fold 하나가 valid set, 나머지 fold들은 모두 train set이 되도록 하여 학습 및 평가를 진행한다.
모든 fold가 한번씩 valid set의 역할을 진행하도록 한다.</p>
</blockquote>
<p>의 과정으로 이루어진다. 그런데 cross_val_predict는 전체 데이터를 예측한 값을 반환한다니..? 대체 무얼 가지고 어떻게 예측한 값을 반환하는 것인가..?</p>
<p>공식 api guide에는 그냥 아주 짧게 method 인자가 predict면 예측한 값을 반환한다고만 나와있었다. 그에 대한 설명은 없더라.</p>
<p>그래서 내가 생각한건 두개였다.</p>
<ol>
<li>X_train, y_train 으로 학습한, 원래 model로 X_train에 대한 예측을 진행한 값</li>
<li>각 fold를 valid로 하고, 나머지를 train 으로 하여 학습, 평가한 모델 중 최고 성능을 낸 모델로 전체 데이터에 대한 예측을 진행한 값.</li>
</ol>
<p>그래서 각각 검증을 해보았다.
1번 가설이 맞다면, 그냥 model.fit 한 후 model.predict한 값과 y_valid_pred가 같아야하는데, 다르다. 기각!
2번 가설이 맞다면, 모델에서 train set으로 사용한 fold에 대한 정확도는 높고, test set으로 사용한 fold에 대한 정확도는 떨어지지 않을까? 라고 생각했다. 그래서 
맞은 것과 틀린 부분을 시각화 해보았더니, 틀린 부분이 아주 고르게 분포하고 있더라.. 그래서 기각!
<img src="https://velog.velcdn.com/images/im_ngooh/post/864667bc-b749-46c5-88e9-8e439b06b283/image.png" alt=""></p>
<p>(사실 시각화에 더 좋은 방법이 있었을 것 같긴 한데..! 일단 저렇게 했다.)</p>
<pre><code class="language-python"># 1. 모델로 예측한 값과, cross_val_predict로 예측한 값이 같은지.

y_cross_pre = cross_val_predict(model, X_train, y_train)

model.fit(X_train, y_train)
y_model_pre = model.predict(X_train)

print(&#39;model accuarcy : &#39;, (y_train == y_model_pre).mean())
print(&#39;cross accruacy : &#39;, (y_train == y_cross_pre).mean())

print(&#39;모델과 cross 사이의 정확도 : &#39; ,(y_cross_pre == y_model_pre).mean())
&gt;&gt;&gt;
다 다르다.</code></pre>
<p>아주 좌절... 결국 뭔지 못찾는건가..? 하다가 공식 문서에서 이어지는 User guide를 읽어보았다..!
<a href="https://scikit-learn.org/stable/modules/cross_validation.html">User-guide</a>
사실 user guide까지는 제대로 읽어본 적 없었는데.. 영어에 대한 막연한 거부감! 오늘 읽어보니까 어렵긴 한데 생각보다는 읽을 만 하더라! 그리고 되게 설명도 잘 되어 있었다! 이렇게 공식문서랑 좀 더 친해졌다.</p>
<p>여기서 발견했다.</p>
<blockquote>
<h4 id="returns-for-each-element-in-the-input-the-prediction-that-was-obtained-for-that-element-when-it-was-in-the-test-set">returns, for each element in the input, the prediction that was obtained for that element when it was in the test set.</h4>
</blockquote>
<p>와...! 수업시간에도 이거 때문에 그렇게 헤매고.. 알아냈다..! 뿌듯해라.
cross_val_predict를 통해 반환되는 예측값은, 각 부분이 test set(valid set)으로 사용되었던 모델에 의해 예측된 값이다!</p>
<p>그러니까, 아래 그림에 대해서
<img src="https://velog.velcdn.com/images/im_ngooh/post/0998e31d-4e87-4bd6-a1f7-2d9d10f464b8/image.png" alt=""></p>
<p>Fold 1 부분에 대한 예측값은 split 1에서 만들었던 모델에서 예측한 값,
Fold 2 부분에 대한 예측값은 split 2에서 만들었던 모델에서 예측한 값,,,
이런 식으로 하여! 각 부분에 대한 예측값들을 합친 값을 반환한 것이다!</p>
<p>와 이해했다..!</p>
<h4 id="의문-2">의문 2</h4>
<p>아니 근데 왜.. 왜... 그럼 cross_val_predict를 사용하는 거지?
실습에서는 cross_val_predict로 예측한 값과 원래 값을 비교해 정밀도를 파악했다. 굳이 model로 예측하여 얻은 값과 비교하지 않고, 이 값으로 정밀도를 파악한 이유는?</p>
<blockquote>
<h4 id="warning">Warning</h4>
<p>Note on inappropriate usage of cross_val_predict
The result of cross_val_predict may be different from those obtained using cross_val_score as the elements are grouped in different ways. The function cross_val_score takes an average over cross-validation folds, whereas cross_val_predict simply returns the labels (or probabilities) from several distinct models undistinguished. Thus, cross_val_predict is not an appropriate measure of generalization error.</p>
</blockquote>
<p>공식문서에는 이런 내용도 있다.</p>
<blockquote>
<p>Results can differ from cross_validate and cross_val_score unless all tests sets have equal size and the metric decomposes over samples.</p>
</blockquote>
<blockquote>
<h4 id="the-function-cross_val_predict-is-appropriate-for">The function cross_val_predict is appropriate for:</h4>
</blockquote>
<p>Visualization of predictions obtained from different models.
Model blending: When predictions of one supervised estimator are used to train another estimator in ensemble methods.</p>
<p>역시 user guide에 있는 내용. 영어...
대강 중요한 내용은, cross_val_predict는 단순히 여러 개별 모델들에 의해 반환된 값들을 가지고 있기 때문에, 일반화된 오류를 파악하기에 적절한 기준은 아니다 라는 것.
그리고 이는 다양한 모델에서 얻은 예측의 시각화 등에 사용하면 좋다는 것 이다.
그렇단다... 솔직히 이해 잘 못했다... ㅎ 특정 조건을 만족시키지 못하면 cross_val_score와 cross_validate의 결과와는 조금 차이가 있을 수 있다는 것 같다..! 알아만 두자.</p>
<p>그냥 위와 별개로 내가 이해한 내용은, cross-validation이라는 것 자체가, test set으로 모델의 성능을 검증할 수 없을 때, train set만 이용하여 모델의 성능을 검증하기 위한 방법이라는 것! 
사실 X_train과 y_train으로 학습한 모델에, X_train을 넣어 예측한 결과의 accuracy가 무슨 큰 의미가 있을까..! 검증의 지표라고 보긴 어려울 것이다. cross-validation을 통해서 test set의 label이 없는 지금 같은 상황에서 어느정도나마 모델의 성능을 평가해 볼 수 있다.
 cross validation을 이용하기 위해, validate, score등의 다양한 함수를 사용할 수 있겠지만, cross_val_predict를 사용한다면 각 부분에 대해서는 학습하지 않은 모델들로 부분들을 예측한 값의 모음, 즉 비교적 평가의 지표로 사용할 수 있는 예측값을 얻을 수 있다. 또한 이 예측값으로는 직접 다양한 계산이나 함수를 통해 여러가지 측정 지표를 계산할 수 있다. 따라서 cross_val_predict를 사용한다!</p>
<p>이렇게 이해했다! cross-validation 끝!</p>
<h2 id="기타">기타</h2>
<ul>
<li>전처리 등을 진행하며 항상 display 등을 이용해 확인해 보는 것을 추천 또 추천!</li>
<li>주피터 노트북에서 esc + f를 누르면 해당 셀에 존재하는 특정 단어를 찾아 다른 단어로 바꿔줄 수 있다.</li>
<li>캐글에서 좋은 솔루션 찾는 법<ol>
<li>Top 키워드로 검색</li>
<li>솔루션에 대한 투표수가 많은 것</li>
<li>프로필 메달의 색상(금색이 젤 조아요, 금색, 빨강, 보라 순!)</li>
</ol>
</li>
<li>헷갈린 부분. X_train 과 y_train으로 학습시킨 모델에 대해, X_train으로 예측한 값을 y_train이랑 비교하면 다 맞아야하는거 아닌가? 응 아니다! 아니지 아니지. 왜 그런 생각을..!</li>
<li>cross validation도, 하이퍼파라미터 튜닝도... model_selection에서 가져오면 된다.</li>
<li>랜덤포레스트는 ensemble에서!</li>
</ul>
<h2 id="더-공부해볼-것">더 공부해볼 것</h2>
<ul>
<li>pd.DataFrame으로 데이터 프레임 만드는 방법. 기본부터 다시!</li>
<li>복습 진짜 열심히 해야겠다 기억도 안나고, 머릿속에서 섞이고. 난리다 난리</li>
<li>뭔가 많았는디..? 흠... 일단 과제랑 미니플젝..!</li>
</ul>
<hr>
<p>그래도 오늘 집중 좀 다시 올라오고, 혼자 복습도 나름 만족스럽게 한 것 같다!
시간이 너무 늦어져서 그렇지 피곤한데.. 내일도 파이팅!</p>
<hr>
<p>해당 내용은 멋쟁이사자처럼 AI School 오늘코드 박조은 강사의 자료를 인용하였습니다. 
<a href="https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html">https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html</a>
<a href="https://scikit-learn.org/stable/modules/cross_validation.html">https://scikit-learn.org/stable/modules/cross_validation.html</a>
<a href="https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html">https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html</a>
<a href="https://thebook.io/080223/ch06/02/02-04/">https://thebook.io/080223/ch06/02/02-04/</a>
<a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.interpolate.html">https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.interpolate.html</a>
<a href="https://stats.stackexchange.com/questions/502037/why-should-we-use-cross-val-predict-instead-of-just-normally-predicting-our-inst">https://stats.stackexchange.com/questions/502037/why-should-we-use-cross-val-predict-instead-of-just-normally-predicting-our-inst</a></p>
<hr>
<p>다음은 퀴즈 시간에 간단히 요약한 내용!</p>
<ol>
<li>pd.get_dummies를 이용하여 one-hot-encoding 하는 법을 배웠다.</li>
</ol>
<p>-&gt; 이때, train set과 test set에 인코딩 결과 같은 피쳐들이 존재하도록 두 데이터를 전처리 해주는 과정이 필수적임을 알게 되었다. (예시 : 호칭에 대해, 한 쪽에만 존재하는 호칭이 존재하므로, 주로 나오는 호칭과 그렇지 않은 &#39;기타&#39;호칭을 구분하여 &#39;기타&#39; 라는  값을 만들어주었다.)</p>
<ul>
<li>전처리를 할 때, 실제 상황에서는 test data는 모르고 있으므로, train 데이터를 기준으로 전처리 한다.</li>
<li>머신러닝을 위해 전처리를 진행 할 때에, train data에 진행한 전처리를 반드시 test data에도 동일하게 진행해줘야 한다는 것을 기억하자.</li>
<li>get_dummies 함수는, 수치형 데이터는 그냥 놔두고 범주형 데이터만 골라내어 one - hot encoding을 진행해준다. 심지어 결측값이 있어도 가능하다. 따라서, get_dummies 함수를 이용한 인코딩은 전처리가 모두 끝난 후 학습 및 평가 데이터를 나눌 때 진행한다.</li>
</ul>
<ol start="2">
<li>결측치 대체 방법에 대해서도 배웠다.</li>
</ol>
<ul>
<li>결측치는 제거하거나, 중앙값 등 다른 값으로 대체하거나, 보간법을 이용해 대체하는 방법이 있다.</li>
<li>오늘은 fillna의 method를 이용하거나 interpolate를 이용해 보간법을 통해 앞, 뒤의 데이터를 사용해 결측치를 대체하는 법을 배웠다.</li>
<li>이는 주로 시계열 데이터 등에서 앞 뒤의 데이터와 연관이 있을때 사용한다.</li>
</ul>
<ol start="3">
<li>cross_val_predict 에 대해서 배웠다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Day 33] Kaggle - Titanic]]></title>
            <link>https://velog.io/@im_ngooh/Day-33-Kaggle-Titanic</link>
            <guid>https://velog.io/@im_ngooh/Day-33-Kaggle-Titanic</guid>
            <pubDate>Tue, 01 Nov 2022 16:30:32 GMT</pubDate>
            <description><![CDATA[<p>22.11.01.
kaggle에서 타이타닉 경진대회에 참여하는 법을 배우며, 드디어 캐글에 대해 알았다!
얼른 여러 모델들도 배우고, 공부도 해서 여러 데이터로 다양한 연습을 해보고 싶다.
그러려면 집중 좀 하자....!!!
그리고 오늘 음 또.. 의사결정나무에 대해 좀 더 자세히 배웠다. 지니 불순도와 정보 엔트로피에 대해 배웠는데, 어렵더라.
그리고 추가 과제 영상을 통해, matplotlib에 대해 이해도를 매우매우 높일 수 있었다. 진짜 짱이다 matplotlib!</p>
<hr>
<h1 id="캐글-시작하기">캐글 시작하기</h1>
<p>회원가입 및 전화번호 인증을 한 후, 
<a href="https://www.kaggle.com/competitions/titanic">캐글 타이타닉</a>
에서 데이터를 다운로드 받았다.</p>
<ul>
<li>train data, test data 그리고 gender_submission.csv파일이 존재한다. 해당 파일은 최종 결과물로 제출해야하는 양식을 알려주기 위해, 여자이면 생존, 남자이면 사망으로 임의적으로 예측해놓은 임시 결과물이다. 해당 파일의 Survived 컬럼에 예측값을 넣어 저장한 csv를 제출하면 된다.</li>
</ul>
<h1 id="eda-및-전처리">EDA 및 전처리</h1>
<ul>
<li>다운받은 데이터를 불러와 살펴본다. train set과 test set에 있는 feature에 대해서도 살펴본다. Survived가 test에는 없는 걸 알 수 있다. train 과 test 데이터의 크기도 비교해본다.</li>
<li>read_csv할때, <code>index_col = &#39;column&#39;</code>으로 인덱스를 설정해줄 수 있다.</li>
<li>데이터를 한번 살펴본다. 결측치도 있고, 데이터 타입도 숫자, 문자 등 다양하다. 전처리가 필요함을 확인한다.</li>
<li>이번 실습에서는 일단 결측치를 모두 0으로 채운 후, 먼저 모델을 만들어 동작하게 한 후, 추후 결측치를 다른 값으로 채워보도록 한다. .fillna(0)으로 간단히 사용하였다.</li>
<li>전처리에는 정규화, 이상치 제거 및 대체, 결측치 제거 및 대체, 인코딩 등이 있다.</li>
<li>주의할 점, test set에서는 결측치를 제거하면 안된다. 인코딩의 경우 범주형 데이터를 수치화하는 것도, 범위가 큰 수치 데이터를 구간으로 나누는 것도 있다.</li>
<li>전처리를 진행할 때에는 train 데이터에 진행한 전처리를 동일하게 test 데이터에도 진행해주어야 한다! 당연!</li>
</ul>
<h1 id="데이터-나누기">데이터 나누기</h1>
<ul>
<li>학습 및 평가 데이터를 나누기 전에, 먼저 컬럼들의 dtype을 살펴본다. 머신러닝 모델의 경우 수치형 데이터만 이용할 수 있기 때문이다. 따라서 feature로는 수치형 데이터만 넣어준다. object 형 데이터 중 EDA 결과 중요한 피쳐가 있다면, 수치형 데이터로 인코딩하여 사용한다. bool 값의 경우 수치형으로 취급된다.</li>
<li>모든 전처리나 데이터를 나누는 과정을 진행하며, 잘 진행되고 있는지 중간중간 변수 값을 확인해주는 것은 필수다! 나중에 오류를 발견하여 헤매지 않게!</li>
</ul>
<h1 id="의사결정나무-알고리즘">의사결정나무 알고리즘</h1>
<ul>
<li>지난번에 의사결정나무를 이용해 분류를 진행하는 알고리즘을 실습했었다. 이번에도 마찬가지로 같은 방식을 이용한다.</li>
<li>다시 의사결정나무가 동작하는 방식을 이해해보자.</li>
<li>의사결정나무는, 여러가지 규칙을 순차적으로 적용하면서 데이터를 분할하는 분류 모형이다.</li>
<li>이때 규칙은, 특정 <code>독립변수</code>에 대해 어떠한 <code>기준값</code>보다 크다 혹은 작다와 같은 방식으로 구성된다. 해당 규칙에 따라 큰 자료들을 하나의 자식노드로, 작은 자료들을 하나의 자식 노드로 나누게 되는 것이다.</li>
<li>그렇게 나누어 내려가다가, 한가지 클래스의 데이터만 존재하는 자식노드는 더 이상 나누지 않고 중지한다.</li>
<li>그럼 이 분할 규칙은 어떻게 정하는가?</li>
<li>바로, 정보이득을 최대로 하는 독립변수와 기준 값을 정한다. 정보이득은 간단히 이해하면 어떠한 조건에 대해 정보 엔트로피가 얼마나 감소하였는가를 나타낸 값이다. 정보 엔트로피가 가장 많이 감소하게 하는 분할 규칙을 찾아 자식노드를 나누게 된다.</li>
<li>따라서, 의사결정나무 알고리즘에는 분할이 제대로 이루어졌는지를 평가하는 지표가 존재한다. 지니계수와 정보 엔트로피가 바로 그것이다.</li>
</ul>
<h3 id="criterion">criterion</h3>
<ul>
<li>지니 불순도
지니 불순도는, 집합에 이질적인 것이 얼마나 섞였는지를 측정하는 지표이다. 이는 어떤 집합에서 한 항목을 뽑아 무작위로 라벨을 추정할 때 틀릴 확률을 의미한다. 공식은 다음과 같다.</li>
</ul>
<p>1에서 각 샘플의 확률의 제곱을 빼준 값이다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/a25b012c-1f98-4f31-b19e-d59d53337c15/image.png" alt=""></p>
<p>집합에 있는 모든 항목이 동일하다면, 지니 불순도 혹은 지니 계수는 0이 되어 최상의 값이다. 반대로, 여러 항목이 균일하게 분포되어 있다면 최악의 값을 가지게 된다. 결정트리에서 분류규칙을 만족하는 샘플과 만족하지 않는 샘플이 같아 확률이 1/2씩이라면 지니 계수는 0.5로 최악의 값이다.</p>
<ul>
<li>엔트로피
와 이거 어렵다! 섀넌 엔트로피라는 것이 무엇을 의미하는지는 명확하게 이해를 못하겠다.</li>
</ul>
<p>다만, DecisionTreeClassifier의 entropy는 Shannon의 정보 이득의 엔트로피를 의미한다. 섀넌 엔트로피(혹은 정보 엔트로피)는, 각 데이터에 포함된 정보의 기댓값(평균)이다. 수식으로는 다음과 같이 표현한다. 밑이 2이다.
<img src="https://velog.velcdn.com/images/im_ngooh/post/582ead82-5524-49a6-8139-c618156aca9d/image.png" alt=""></p>
<p>정보 엔트로피가 크다는 것은, 각 데이터에 포함된 정보의 기댓값이 크다는 것, 사건을 관측했을 때 더 많은 정보를 얻을 수 있다는 것이다. 이는 변수의 불확실성이 높다는 것이며, 결국 확률이 낮음을 의미한다.
이렇게 엔트로피가 불확실성이면서 동시에 평균 정보량을 의미한다는 것을 파악할 수 있다. 사건의 확률이 높으면 발생해도 많은 유용한 정보를 제공하지 않으나, 사건의 발생 확률이 희박하면 발생하였을 때 더 많은 정보를 제공한다. 주사위던지기와 동전던지기의 예시를 생각해보면 된다. 주사위던지기의 엔트로피가 동전던지기보다 크다. 확률이 작고, 정보량이 많다.</p>
<p>모든 사건의 발생 확률이 동일한 경우 비트의 개수는 섀넌 엔트포리와 동일하다. 따라서 분류 문제에서, 클래스의 개수가 2의 N승이라면 최대 엔트로피가 N으로 정해진다. 반면 하나의 사건이 확실하게 일어나는 경우라면 엔트로피는 0 이 된다.</p>
<p>따라서 이 역시, 데이터에 클래스들이 얼마나 섞여있는지에 대한 지표가 된다. 클래스가 하나만 존재한다면 엔트로피는 0으로 최소가 될 것이고, 여러 클래스가 같은 확률로 존재한다면 엔트로피는 N으로 최댓값이 될 것이다.</p>
<p>추가로, 파이썬에서 로그는 <code>np.log2(N)</code>과 같이 쓸 수 있다.</p>
<ul>
<li><p>엔트로피나 지니불순도가 0이 될 때는 보통 샘플이 [1, 0] 이나 [2,0] 처럼 샘플의 개수가 적을 때가 많은데 이렇게 너무 자세하게 학습하면 일반화 하기 어려워져 과적합이 발생할 수 있다. 그러면 아마 min_samples_leaf나 max_depth를 설정하여 조정해줄 수 있겠다!</p>
</li>
<li><p>이외에도 logloss라는 것을 이용할 수 있는데, 이건 나중에 배울 듯! 오늘은 멀티클래스일 경우에는 분류를 특정 클래스의 확률 예측으로 진행할 수 있고, 이때 logloss를 사용한다고만 들었다.</p>
</li>
</ul>
<hr>
<h1 id="matplotlib">matplotlib</h1>
<p>Youtube 강의 <a href="https://www.youtube.com/watch?v=ZTRKojTLE8M&amp;list=WL&amp;index=1&amp;ab_channel=PyConKorea">혼란한 matplotlib에서 질서찾기 - 이제현</a></p>
<p>와 matplotlib이 무엇인지 이걸 보고 좀 이해가 되었다.
그리고 matplotlib을 잘 사용하는 법도!</p>
<p>matplotlib을 잘 사용하기 위해선, matplotlib 생태계 전체를 잘 활용해야 한다.
그리고 matplotlib 자체에서도 상태기반 방식이 아닌, 객체지향 방식을 사용해야 한다.</p>
<h3 id="matplotlib-생태계-활용하기">matplotlib 생태계 활용하기</h3>
<p>matplotlib은 numpy 기반이다.
그리고 matplotlib을 기반으로 하는 다양한 라이브러리, seaborn, Geopandas, NetworkX, scikit-learn 등이 존재한다.
이 생태계를 잘 활용해야 한다. 결국 생태계 내 어떤 라이브러리이든, matplotlib 객체를 반환한다는 것을 명심하자!</p>
<ul>
<li><p>시각화 진행 전, 스타일 설정이 편한 seaborn을 활용해 matplotlib 객체의 스타일 설정을 잘 해준다.</p>
</li>
<li><p>matplotlib으로 화면 구성을 설정한다.</p>
</li>
<li><p>그 후, 생태계 내의 다양한 라이브러리를 사용해 그래프에 사용할 데이터를 얹어준다.!!!!!
이게 핵심이다. 예를 들어, violin plot을 그릴거라면, seaborn으로 간단히 violin plot을 그려준다. 지도를 그릴거라면 Geopandas를 사용한다.</p>
</li>
<li><p>그 후, 결국 반환된 것은 Matplotlib 객체이므로, matplotlib의 객체지향 방식을 사용해 요소 하나하나를 건드려가며 더 설득력있고, 눈에 잘 들어오는 시각화를 진행하면 된다.</p>
</li>
</ul>
<h3 id="객체-지향-방식">객체 지향 방식</h3>
<ul>
<li>matplotlib의 사용 방식으로는 상태기반 방식과 객체 지향 방식이 있다. 는 것 까지만 알고 있었는데... 오늘 좀 느낌이 왔다!</li>
<li>상태기반방식은, 그림을 그리는 순서대로 코드를 작성하여 진행하는 방식이다. plt.~~를 사용하여 코드를 진행하는 것이 상태기반 방식을 활용하는 것이라고 생각하면 된다. </li>
<li>반면 객체지향방식은, 대상을 지정한 후에 그 대상을 그리는 방식이라고 생각하면 된다. 예를 들어 fig, ax, plot, label, legend, suptitle, line(선), collections(면) 등 다양한 객체를 지정하여 직접 접근하고, 각각의 속성을 바꾸어줄 수 있다.</li>
<li>객체.set을 통해 특정 속성을 제어할 수 있다.</li>
</ul>
<p>객체지향방식은 상태기반방식의 명확한 한계를 극복한다. 요소 하나하나에 직접 접근하여 세부적인 시각화를 진행할 수 있다. 순서대로 진행하기 때문에 여러 반복되는 코드를 작성해야 했던 상태기반 방식과는 달리 여러 객체에 접근하기 위해 반복문을 사용할 수도 있다.</p>
<p>ax.add_artist()를 통해 다양한 보조 도형 역시 추가할 수 있다!</p>
<p>일단 이 정도만 이해 했다. 자세한 사용법도 공부해보면 어느정도 수준까지는 금방 할 수 있지 않을까 싶다! matplotlib으로 이 정도 수준의 시각화를 해낼 수 있다는 것도 놀라웠고, 객체 지향 방식으로 matplotlib을 사용하는 법을 알게 되어 좋았다.
나중에 좀 자세한 시각화를 진행할 일이 있으면, 이 방법을 시도해봐도 좋겠다!</p>
<hr>
<p>해당 내용은 멋쟁이사자처럼 AI School 오늘코드 박조은 강사님의 자료를 인용하였습니다.
<a href="https://datascienceschool.net/03%20machine%20learning/12.01%20%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95%EB%82%98%EB%AC%B4.html#id2">의사결정나무</a>
<a href="https://ko.wikipedia.org/wiki/%EC%A0%95%EB%B3%B4_%EC%9D%B4%EB%93%9D">정보이득</a></p>
<hr>
<h4 id="더-공부해볼-것">더 공부해볼 것</h4>
<ul>
<li>판다스에서 categorical 변수 다루는 법을 좀 찾아봐야겠다. cat 접근자랑!</li>
<li>어우 시간이 왜이렇게 오래걸렸지ㅠㅠ 집중하는 법은 어디 없나!</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>