under prediction을 주는 부분 고민

이를 어떻게 loss function (손실 함수) 안에 반영시킬 수 있을 것인가?

 

under prediction이라는 것에 대해 회고해보자.

 

t_i : target label

y_i : prediction

 

t_i > y_i일 때 under prediction이 되었다고 할 수 있을 것.

 

배달 시간 예측같은 경우는 예상 시간이 실제 배달 시간보다 더 걸리게 될 경우 소비자의 불만이 더 클 것. 그래서 더더욱 under prediction을 방지해야 함.

 

이를 잘 valancing할 수 있는 loss function을 만드는 것이 우리의 목표

 

loss function을 만들 때 가져야 하는 특징

 

t_i ≥ y_i -> (t_i - y_i)^2

t_i < y_i -> 1/2(t_i - y_i)^2

 

위의 두 가지 경우가 가능.

각각의 경우에 따라 다른 가중치를 가진 squared loss function으로 줄 수 있다.

이걸 하나의 식으로 표현하려면 다음과 같이 하면 된다.

 

tensorflow에서 기본적으로 주어진 squared error function을 확장시켜 custom한 loss function으로 바꾸는게 어렵지 않다.

keras api를 쓰면 간단해진다.


ML 커리어 종류

 

  • ML research scientist
    • 모델을 만드는 사람
  • ML research engineer
    • 시스템 운영, 구현 부분에 초점
  • Data scientist (analytics)
    • 유저들 행동 로그 등의 데이터 지표를 분석하는 직업으로 따로 구분해 부르기도 한다.
    • 크게는 머신러닝 엔지니어와 통합하여 쓰기도 함.

 

회사가 커지면 커질수록 분업이 생기게 된다.

 

ML 커리어 과정

 

  • Individual contributor (IC)
    • research scientist -> senior research scientist -> principle research scientist -> senior principle research scientist -> VP -> senior VP -> CTO 
  • Manager
    • manager(처음에 individual contributor로 join해서 일을 하다 manager로 선회하는 경우가 대부분) -> senior manager -> director -> senior director -> VP -> senior VP -> CEO

ML 취업

 

  • 과정
    • 온라인지원(linkedin), 인맥을 통한 referral, 리크루터로부터 연락
    • Phone screening (이력서랑 과거에 했던일이 일치하는지 확인)
    • On-site interview
    • Offer
  • Resume
    • 간결하게 impact 위주로, 부풀리지 말 것.
      • 강조한 부분에 대해 면접에서 집중 질문을 받기 때문에 실제로 안한 부분에선 굉장히 크게 minus될 수도 있다. 그렇기 때문에 내가 맡았던 부분이 정확히 어떤 부분이었는지에 대해 기입하는게 좋다.
  • 여러 군데 지원 시 유의점
    • 가장 가고 싶은 곳의 인터뷰 스케쥴을 먼저 잡을 것
    • 비슷한 시기에 오퍼를 받을 수 있다면 협상에 도움
  • 면접 관련 구성원들
    • Hiring manager 
      • 사람을 뽑으려는 팀의 팀장이 보통.
    • Recruiter
      • 인사팀장. 
      • position에 대해 자세히 알고있지 못하는 경우가 많다. 최대한 Hiring manager가 원하는 사람을 찾는 사람
    • Interviewers
      • 인터뷰하는 사람들. 보통 Hiring manager 같은 레벨에 있고 다른 팀인 사람 혹은 선임 혹은 팀의 팀원들로 구성
  • 면접 준비
    • 회사, 팀, 인터뷰어에 대한 사전조사 (경력이나 인터뷰어가 어떤 면접 질문을 하는지 알아둘 것)
      • 회사가 풀고 있는 문제에 대해 알고 있는 것이 중요.
    • 기본 재점검
    • 응용분야 지식 보완
    • 코딩
      • 코딩보단 ML 전문성을 더 보는 경우도 있고.. 팀바팀이다.
  • 면접
    • 코딩 (많으면 1명 절대 2명 이상은 안물어본다...)
    • ML 지식 (최소 1명 최대 2명..) (최신 연구결과보다 기초가 중요)
    • 시스템 디자인 (이 시스템을 어떻게 design할 것인지. 성공지표, 실험설계 등 포함)
      • 모델을 어떻게 측정할 것인지 - 성공지표(metric)을 어떤걸 써야 모델을 잘 만들 수 있을 지.
      • 어떤식으로 실험을 설계해야할지.. 모델을 launching했을 때 어떤 식으로 사용자들이 이것을 평가할 수 있게 user를 어떻게 묶을 것인지.. (나이? 성별? 직업?)
    • 과거 프로젝트 경험 (명확한 문제정의, 본인의 기여)
      • 이 문제가 얼마나 어려운 문제였고, 내가 얼마나 어려운 / 중요한 문제를 풀었는지
      • 이 안에서 내가 얼마나 기여를 했는지 명확하게 기억하는 게 중요.
    • 회사문화, 팀문화
      • 회사랑 팀이랑 어울리는가를 보는 면접관들이 한명정도 있을 수 있다.
      • 나의 경험이 내가 이런 사람이라는 걸 보여주는 상황을 설명해야 함. 그리고 내가 그 상황에서 어떤 action을 취했고, 이 action때문에 바뀌어진 결과에 대해서 말하기
  • 오퍼 받은 후
    • 시장조사 후 적절한 연봉협상할 것
      • 절대 바로 받지 말고 한 번 이상은 협상을 해봐야 한다!
        • 학교 졸업하고 바로 들어갈 땐 서툴러서 처음 제시된 걸 그대로 받을 뻔 했지만.. 소심하게 얘기했다가 살짝 올려줬다고 하신다..!
        • 여러 개의 offer가 있는 것이 확실하다. 하나만 있으면 올려달라고 말할 순 있지만 반영될 확률이 낮다. 그러나 두 개 이상있으면 두 개 사이에서 협상할 확률이 굉장히 높다.
        • 세 가지 요소
          • 매달 들어오는 월급
          • 매년 주식으로 받을 수 있는 금액(보통 한꺼번에 줌. 향후 3년, 4년동안 1/4씩 주기도 함)
          • 매년마다 받을 수 있는 보너스 (연봉의 20% 25% 회사마다 다름)
        • 회사의 상장 가능성도 볼 것. 상장 가능성이 보이면 base(월급)를 적게 받더라도 주식을 받으면 나중에 훨씬 이득을 볼 수 있을 것이다. 그게 아니고 stable한.. 변동이 심할 것 같지 않으면 base를 낮게 받는 것이 불리할 것....
      • 다수의 오퍼가 있다면 협상에 절대적으로 유리하다
      • Hiring manager, recruiter들과 좋은 관계 유지하기
  • 인턴은 쌍방으로 서로를 평가하는 것!

'AI > KDT 인공지능' 카테고리의 다른 글

[06/24] 심층학습 기초  (0) 2021.06.24
[06/23] 다층 퍼셉트론  (0) 2021.06.23
[06/21] 신경망의 기초  (0) 2021.06.21
[06/16] 인공지능과 기계학습  (0) 2021.06.16
[06/15] 분류문제 실습  (0) 2021.06.15

사람의 뉴런

 

  • 두뇌의 가장 작은 정보처리 단위
  • 구조
    • 세포체는 간단한 연산
    • 수상돌기는 신호 수신
    • 축삭은 처리 결과 전송
  • 사람은 10^11개 정도 뉴런을 가지며, 각 뉴런은 약 1000개 다른 뉴런과 연결돼 10^14개 연결을 갖는다.

 

컴퓨터가 사람 뇌의 정보처리를 모방해 지능적 행위를 할 수 있는 인공지능 도전

-> 뉴런의 동작 이해를 모방한 초기 인공 신경망(artificial neural network, ANN) 연구 시작

-> 퍼셉트론 고안

 

사람 신경망 인공 신경망
세포체 노드
수상돌기 입력
축삭 출력
시냅스 가중치

신경망의 종류

 

인공신경망은 다양한 모델이 존재

 

  • 전방(forward) 신경망과 순환(recurrent) 신경망
  • 얕은(shallow) 신경망과 깊은(deep) 신경망

 

결정론(deterministic) 신경망과 확률론적(stochastic) 신경망 비교

  • 결정론 신경망
    • 모델의 매개변수와 조건에 의해 출력이 완전히 결정되는 신경망
  • 확률론적 신경망
    • 고유의 임의성을 갖고 매개변수와 조건이 같더라도 다른 출력을 가지는 신경망

퍼셉트론

 

  • 구조 : 절(node), 가중치(weight), 층(layer)과 같은 새로운 개념의 구조 도입
  • 제시된 퍼셉트론 구조의 학습 알고리즘 제안
  • 원시적 신경망이나, 깊은 인공신경망을 포함한 현대 인공신경망의 토대
    • 깊은 인공신경망은 퍼셉트론의 병렬 배치를 순차적으로 구조로 결합함
  • 현대 인공신경망의 중요 구성 요소가 된다.

퍼셉트론의 구조

 

  • 입력
    • i번째 노드는 특징 벡터의 요소 x=(x_1,x_2,...,x_d)^T의 요소 x_i를 담당
    • 항상 1이 입력되는 편향(bias) 노드 포함
  • 입력과 출력 사이 연산하는 구조를 가진다.
    • i번째 입력 노드와 출력 노드를 연결하는 변(edge)는 가중치 w_i를 갖는다.
    • 퍼셉트론은 단일 층 구조라 간주.
  • 출력
    • 한 개의 노드에 의해 수치(+1 혹은 -1) 출력 -> 활성 함수를 step function을 사용할 때

퍼셉트론의 동작

 

  • 선형 연산 -> 비선형 연산
    • 선형 : 입력(특징)값과 가중치를 곱하고 모두 더해 s를 구함
    • 비선형 : 활성 함수 τ 적용
      • 활성함수로 계단함수를 사용하면 출력이 +1 또는 -1 출력
  • 수식
    • y= τ(s)
    • 이 때 s = sigma^d_(i=1)w_ix_i, τ(s)={1 (s≥0), -1 (s<0)}
  • 퍼셉트론의 동작을 식으로 작성하면 다음과 같다.
    • y = τ(w^Tx) (x는 엄밀히 따지면 d+1일 것이다. 여기서 +1은 편향 값.

퍼셉트론의 학습

 

  • 분류기 학습 과정
    1. 과업 정의와 분류 과정의 수학적 정의 (가설 설정)
    2. 해당 분류기의 목적함수 J(Θ) 정의
    3. J(Θ)를 최소화하는 Θ를찾기 위한 최적화 방법 수행
  • 목적함수 정의 (1단계 + 2단계)
    • 퍼셉트론의 매개변수를 w = (w_0, w_1, ..., w_d)^T라 표기하면, 매개변수 집합은 Θ={w} 표기
    • 목적함수를 J(Θ) 또는 J(w)로 표기
    • 퍼셉트론 목적함수 상세 조건
      • J(w)≥0이다.
      • w가 최적 즉, 모든 샘플을 맞히면 J(w)=0이다.
      • 틀리는 샘플이 많은 w일수록 J(w)는 큰 값을 갖는다.
  • 목적함수 상세 설계
    • Y는 w가 틀리는 샘플의 집합
    • 위 식은 세 가지 조건을 만족하므로 퍼셉트론 목적함수로 적합
      • 임의의 샘플 x_k가 Y에 속하면(오분류됐을 때) 퍼셉트론의 예측 값 w^Tx_k와 실제 값 y_k는 부호가 다르다 -> -y_k(w^Tx_k)는 항상 양수를 가짐 : 만족 (조건 1 만족)
      • Y가 공집합일 때 (퍼셉트론이 모든 샘플을 맞출 때) , J(w)=0 : 만족 (조건 2 만족)
      • Y가 클수록 (틀린 샘플이 많을수록) J(w)는 큰 값을 가짐 : 만족 (조건 3 만족)
  • 경사하강법gradient descent
    • 최소 J(Θ) 기울기를 이용해 반복 탐색하여 극값을 찾는다.
    • 경사도 계산
      • 일반화된 가중치 갱신 규칙 Θ=Θg를 적용하려면 경사도 g가 필요
      • J(w)를 편미분하면
      • 델타 규칙 (퍼셉트론 학습 방법)
  • 퍼셉트론 학습 알고리즘 (확률론적stochastic 형태)
    1. 난수를 생성하여 초기해 w 설정
    2. repeat
    3.     Χ의 샘플 순서를 섞는다.
    4.     quit = ture
    5.     for j = 1 to n
    6.         y = τ(w^Tx_j)
    7.         if(y≠y_j)
    8.             quit = false
    9.             for i = 0 to d
    10.                 w_i = w_i + ρy_jx_ji
    11. until(quit)
    12. what = w
  • 퍼셉트론 학습 알고리즘 (무리batch 형태)
    1. 난수를 생성해 초기해 w 설정
    2. repeat
    3.     Y = 0 // 틀린 샘플 집합
    4.     for j = 1 to n
    5.         y = τ(w^Tx_j)
    6.         if(y≠y_j) Y = Y∪x_j
    7.     if(Y≠0)
    8.         for i=0 to d
    9.             w_i = w_i + ρ(sigma(y_kx_ki)_x_k)
    10. until (Y=0)
    11. what = w

 

 

 

 

'AI > KDT 인공지능' 카테고리의 다른 글

[06/23] 다층 퍼셉트론  (0) 2021.06.23
[06/22] 라이브 세션  (0) 2021.06.22
[06/16] 인공지능과 기계학습  (0) 2021.06.16
[06/15] 분류문제 실습  (0) 2021.06.15
오토인코더, t-SNE  (0) 2021.06.14

인공지능

 

인공지능이란? 인간처럼 생각하고 행동하는 기기를 만드는 기술

 

인공지능은 레고처럼 조립이 가능하다.

이를 가능하게끔 해주는 조력자는 다음과 같은 것들이 있다.

 

  • Theano
  • Pytorch
  • Keras
  • the Microsoft Cognitive toolkit
  • Caffe2
  • TensorFlow
  • mxnet
  • GLUON
  • Chainer
  • Caffe

인공지능은 도구이다. 도구를 만드는 방법도 중요하지만, 도구를 사용하는 방법도 배워야 한다.

목적에 적당한 도구를 고르는 방법도 알아야 할 것이고, 

고른 도구를 어떻게 사용하는지도 알아야 할 것이다.


기계 학습

 

초창기 : 컴퓨터가 경험을 통해 학습할 수 잇도록 프로그래밍할 수 있다면, 세세하게 프로그래밍 해야 하는 번거로움에서 벗어날 수 있다.

Samuel, 1959
현대 : 어떤 컴퓨터 프로그램이 T라는 작업을 수행할 때, 이 프로그램의 성능을 P라는 척도로 평가하자. 이 때, 경험 E를 통해 성능이 개선되면 이 프로그램은 학습을 했다고 할 수 있다.

Mitchell, 1997

즉, 최적의 프로그램(알고리즘)을 찾는 행위이다.

 

경험 E를 통해 주어진 작업 T에 대한 성능 P의 향상 => E * T = P 

 

기존의 프로그래밍과 기계학습은 무엇이 다를까?

 

기존의 프로그램은 입력값을 넣어주고, 규칙을 주면 그 규칙에 대한 값을 Sequence하게 나열하고 서술한다고 하면,

기계 학습은 입력값과 결과를 주고, 그 안에 점진적으로 좋아지는 규칙을 찾으라는 것이다.

 

초창기 인공지능은 지식기반 방식이었다.

여기서 지식기반이란, 경험적 지식 혹은 사실을 인위적 컴퓨터에 부여하여 학습하였다.

그러나 이에는 한계가 있었다. 학습의 대상이 심한 변화 양상을 갖는 경우, 모든 지식 혹은 사실의 나열이 불가능했다.

 

기계 학습의 문제(task)는 예측(prediction)이다.

이 때, 예측은 회귀(Regression)와 분류(Classfication)로 나뉜다.

회귀는 목표치가 실수이고, 분류는 부류 혹은 종류의 값으로 나타난다.

 

기계 학습의 첫 단계에선 우선 데이터를 관찰한다.

그리고 그 데이터에 대한 모델 즉, 가설(Hypothesis)을 세운다. ex) 데이터 양상이 직선 형태를 보인다 -> 모델을 직선으로 선택한다고 가정한다.

가설인 직선 모델의 수식을 세운다. ex) 2개의 매개변수(parameter)와 w와 b -> y = wx + b

가설을 세운 모델에 대해서 예측을 가장 정확하게 하는 최적의 매개변수를 찾는다.

처음은 임의의 매개변수 값에서 시작하지만, 이를 개선하여 정량적인 최적 성능(Performance)에 도달하도록 한다.

 

훈련을 마치게 되면, 추론(Inference)을 수행한다.

새로운 특징에 대응되는 목표치의 예측에 사용한다. 

 

결국, 기계 학습의 궁극적 목표는 훈련 집합에 없는 새로운 데이터에 대한 오류를 최소화시키고 싶은 것이다.

이러한 테스트 집합(새로운 데이터)에 대한 높은 성능을 일반화(Generalization) 능력이라고 한다.

 

기계 학습의 필수요소

 

  • 학습할 수 있는 데이터
  • 데이터의 규칙이 존재
  • 수학적으로 설명이 불가능해야 한다.
    • 수학적으로 설명이 되면 수학적으로 모델링을 하면 된다.
    • 수학적으로 모델링이 되지 않는(블가능한) 영역을 찾아내는 것이 기계 학습의 역할.

 

특징 공간

 

모든 데이터는 정량적으로 표현되며, 특징 공간 상에 존재하게 된다.

이 특징 공간은 데이터의 차원에따라 1차원에서부터 2차원, ... , 다차원 특징 공간으로 확장될 수 있다.

 

d-차원 데이터에서 

직선 모델을 사용했을 때 매개변수의 수는 d+1이다.

2차 곡선 모델을 사용하면 매개변수 수가 지수적으로 증가하여 d^2+d+1이 될 것이다.

d차 곡선 모델을 사용해도 이는 마찬가지일 것.

 

이러한 모델을 설정할 때 각 특징마다의 거리가 있을 것이다. 이 때, 데이터가 차원의 공간상에 존재하게 되고, 데이터간의 거리가 가까울수록 데이터의 유사도가 높다라고 일반적으로 평가를 내리게 된다. 이 거리라는 개념을 통해서도 규칙을 찾을 수 있게 된다.

  • 유클리드 거리

 

차원의 저주

 

차원이 높아짐에 따라 발생하는 현실적인 문제들을 일컫는 말이다.

차원이 높아질수록 유의미한 표현을 찾기 위해 지수적으로 많은 데이터가 필요하다. 

 

이를 보완하기 위하여 특징 공간을 변환한다. 이 때, 변환할 수 있는 공식을 새롭게 정의하면 다차원에서 제대로 해결할 수 없었던 문제를 해결할 수 있게 된다. 이를 표현 문제(representations matter)라고 한다.

 

표현 학습(representation learning)

 

좋은 특징 공간을 자동으로 찾는 작업이다.

 

심층 학습(Deep Learning)

 

표현학습의 하나로 다수의 은닉층을 가진 신경망을 이용해 최적의 계층적 특징을 학습하는 것이다.

 

인공지능의 단계

 

  • 약인공지능 (현재의 단계)
    • 인간이 지시한 명령의 틀 안에서만 일하기때문에 예측과 관리 용이
  • 강인공지능
    • 인간이 할 수 있는 어떠한 지적 업무도 성공적으로 해낼 수 있는 가상적 기계 지능
  • 초인공지능
    • 인공지능의 발전이 가속화되어 모든 인류의 지성을 합친 것보다 더 뛰어난 인공지능

데이터

 

과학 기술의 정립 과정

 

데이터 수집 -> 모델 정립 (가설 Hypothesis) -> 예측

 

ex) 천동설은 수집한 데이터에 대해 설명하지 못하여 틀린 모델.

그러나 지동설은 제 1, 제 2, 제 3법칙을 완성하여 옳은 모델임을 증명하였음.

 

기계 학습

 

  • 기계학습은 복잡한 문제 혹은 과업을 다룬다.
    • 지능적 범주의 행위들은 규칙의 다양한 변화 양상을 가짐.
  • 단순한 수학 공식으로 표현 불가능함
  • 데이터를 설명할 수 있는 학습 모델을 찾아내는 과정
  • 기계 학습 문제는 데이터 생성 과정을 알 수 없다. 단지 주어진(규칙 x) 훈련집합 X, Y로 가설 모델을 통해 근사 추정만이 가능하다.

 

데이터의 중요성

 

  • 데이터의 양과 질
    • 주어진 과업에 적합한 다양한 데이터를 충분한 양만큼 수집하면 과업 성능이 향상한다.
      • 수학적으로 설명이 안 되는 규칙을 모델(가설)을 통해 설명하고 싶다. 이 때, 데이터가 많으면 많아질수록 그에 관한 훨씬 더 많은 규칙, 정보를 알 수 있게 된다.
  • 공개 데이터
    • 대표적 3가지 데이터 : Iris, MNIST, ImageNet
    • UCI 저장소
  • 적은 양의 데이터베이스로 높은 성능을 달성하는 법
    • 방대한 공간에서 실제 데이터가 발생하는 곳은 매우 작은 부분 공간이다
      • 데이터 희소(Data sparsity) 특성을 가정한다.
      • 매니폴드 가정(manifold assumption (or manifold hypothesis))
        • 고차원의 데이터를 저차원으로 투영시켜 봐서 유사한 규칙을 찾는다. 고차원에서의 규칙과 저차원에 투영했을 때의 규칙은 유지된다.

간단한 기계 학습의 예

 

기계 학습이 할 일을 공식화하면,

 

θ_hat = argmin J(θ)

 

기계 학습은 작은 개선을 반복해 최적의 해를 찾아가는 수치적 방법으로 위 식을 푼다.

이를 알고리즘 형식으로 쓰면

 

1 난수를 생성하여 초기 해 θ_1을 설정

2 t=1

3 while (J(θ_t)가 0.0에 충분히 가깝지 않음) # 수렴 여부 검사

4    J(θ_t)가 작아지는 방향 △θ_t를 구함. # △θ_t는 주로 미분을 사용해 구함

5    θ_(t+1) = θ_t + △θ_t

6    t = t+1

7 θ_hat = θ_t

 

카드 승인 예제

 

요소

  • input
    • x
    • customer application
  • output
    • y
    • approve or deny -> classification 문제
  • target distribution
    • f = P(y|x)
    • ideal credit approval formula
  • data
    • (x_1, y_1), ..., (x_n, y_n)
    • historical records
  • hypothesis
    • g : X -> Y
    • formula to be used

 

x = {x_1, x_2} where x_1 : age and x_2 : annual salary in USD

N=11, d=2, X = R^2, and y = {approve, deny}

 

dataset D

 

n x_1 x_2 (k) y
1 29 56 approve
2 64 89 approve
3 33 17 deny
4 45 94 approve
5 24 26 deny
6 55 24 deny
7 35 52 approve
8 57 65 approve
9 45 32 deny
10 52 75 approve
11 62 31 deny

 

기계학습 설정

 

교사학습의 경우

 

모델(가설) 선택

 

  • 과소적합 (underfitting)
    • 모델의 용량(자유도(파라미터와 비례))이 작아 오차가 클 수 밖에 없는 현상
    • 대안 : 비선형 모델을 사용
      • 선형 모델에 비해 오차가 크게 감소.
  • 과대적합 (overfitting)
    • 모델이 훈련집합에 대해 거의 완벽히 근사.
    • 그러나 새로운 데이터를 예측한다면 큰 문제 발생
    • 이유는 모델의 용량이 크기 때문에 학습 과정에서 잡음까지 수용.

편향(bias)과 분산(변동, variance)

 

훈련집합을 여러 번 수집해 1차 ~ 12차에 반복 적용하는 실험을 한다고 가정하자.

 

  • 2차일 때
    • 매번 큰 오차. -> 편향이 크다.
    • 하지만 비슷한 모델을 얻음 -> 변동이 낮다.
  • 12차일 때
    • 매번 작은 오차. -> 편향이 작다.
    • 하지만 크게 다른 모델을 얻음 -> 변동이 높다.
  • 일반적으로 용량이 작은 모델은 편향이 크고 분산이 작고, 복잡한 모델은 편향이 작고 분산이 큼.
  • 즉, 편향과 분산은 상충(trade-off) 관계이다.

 

기계 학습의 목표는 낮은 편향과 낮은 분산을 가진 예측 모델을 만드는 것

그러나 모델의 편향과 분산은 상충 관계.

따라서 편향을 최소로 유지하며 분산도 최대로 낮추는 전략이 필요하다.


검증집합과 교차검증을 이용한 모델 선택 알고리즘

 

검증집합을 이용한 모델 선택

 

훈련집합과 테스트집합과 다른 별도의 검증집합(validation set)을 가진 상황 (데이터 양이 많을 때)

 

검증집합을 이용한 모델 선택 알고리즘

 

입력 : 모델집합 Ω, 훈련집합, 검증집합, 테스트집합

출력 : 최적 모델과 성능

 

1 for ( Ω에 있는 각각 모델)

2    모델을 훈련집합으로 학습시킨다.

3    검증집합으로 학습된 모델의 성능 측정 # 검증 성능 측정

4 가장 높은 성능을 보인 모델 선택

5 # 테스트집합으로 선택된 모델 성능 측정 # 웬만해선 최후의 수단으로..

 

교차검증을 이용한 모델 선택

 

교차검증(cross validation)

 

비용 문제로 별도 검증집합이 없는 상황에 유용한 모델 선택 기법 (데이터 양이 적을 때)

훈련집합을 등분해 학습과 평가 과정을 여러 번 반복 후 평균 사용

 

교차검증을 이용한 모델 선택 알고리즘

 

입력 : 모델집합 Ω, 훈련집합, 테스트집합, 그룹 개수 k

출력 : 최적 모델과 성능

 

1 훈련집합을 k개 그룹으로 등분

2 for ( Ω에 있는 각각 모델)

3        for ( i=1 to k)

4            i번째 그룹을 제외한 k-1개 그룹으로 모델 학습

5            학습된 모델 성능을 i번째 그룹으로 측정 

6        k개 성능을 평균해 해당 모델 성능으로 취하기

7 가장 높은 성능 보인 모델 선택

8 # 테스트집합으로 선택된 모델 성능 측정

 

부트스트랩(bootstrap)

 

임의의 복원 추출 샘플링(sampling with replacement) 반복

데이터 분포가 불균형일 때 적용한다.

 

부트스트랩 알고리즘

 

입력 : 모델집합 Ω, 훈련집합, 테스트집합, 샘플링 비율 p(0<p≤1), 반복횟수 T

출력 : 최적 모델과 성능

 

1 for ( Ω에 있는 각각 모델)

2        for ( i=1 to T)

3            훈련집합 X에서 pn개 샘플을 뽑아 새로운 훈련집합 X'를 굿헝한다. 이 때 대치 허용.

4            X'로 모델 학습

5            X-X'를 이용해 학습된 모델 성능 측정

6        7개 성능을 평균해 해당 모델 성능으로 취한다.

7 가장 높은 성능을 보인 모델 선택

8 테스트 집합으로 선택된 모델 성능 측정

 

이상탐지, 보안에서 주로 쓰이는 알고리즘이다.


현실에서는 위와 같은 알고리즘을 통해 모델을 선택하는 것보다는

경험으로 큰 틀(가설)을 선택한 후,

모델 선택 알고리즘으로 세부 모델을 선택함

이런 경험적 접근 방법에 대해 『Deep Learning』책에서는 다음과 같이 비유하였다.

어느 정도 우리가 하는 일은 항상 둥근 홈(선택 모델)에 네모 막대기(데이터 생성 과정)를 끼워 넣는 것이라 할 수 있다.

Goodfellow2016(222쪽)

 

현대 기계 학습은

용량이 충분히 큰 모델을 선택 후,

선택한 모델이 정상을 벗어나지 않도록 여러 규제(Regularizaiton, 모델의 용량을 줄여준다.)기법을 적용한다.


규제

 

데이터 확대

 

데이터를 더 많이 수집하면 일반화 능력이 향상된다.

그러나 데이터 수집에는 많은 비용이 든다. -> 실측 자료(ground truth)를 사람이 일일이 표식(Labeling)해야 하기 때문에..

그래서 인위적으로 데이터를 확대(Data Augmentation)한다.

 

  • 훈련집합에 있는 샘플을 변형(transform)
  • ex) 약간 회전(rotation) 또는 왜곡(warping) 단, 원 데이터의 부류 소속 등의 고유 특성이 변하지 않게 주의한다.

 

가중치 감쇠

 

개선된 목적함수를 이용해 가중치를 작게 조절하는 규제 기법이다.

 

 

λ는 주어진 가중치의 감쇠 선호 정도를 제어한다.


기계 학습 지도 방식에 따른 유형

 

  • 지도 학습(Supervised learning)
    • 특징 벡터 X와 목표치 Y가 모두 주어진 상황
    • 회귀(Regression)와 분류(Classification) 문제로 구분
  • 비지도 학습(Unsupervised learning)
    • 특징 벡터 X는 주어지나, 목표치 Y가 주어지지 않는 상황
    • 군집화(Clustering) 과업 
      • ex) 고객 성향 맞춤 홍보
    • 밀도 추정(density estimation), 특징 공간 변환 과업 (ex) PCA)
  • 강화 학습(Reinforcement learning)
    • 상대적 목표치가 주어지는데, 지도 학습과 다른 형태. -> 보상(Reward)
    • ex) 바둑
      • 수를 두는 행위가 샘플. 게임이 끝나면 목표치 하나가 부여.
        • 이기면 1, 패하면 -1 부여
      • 게임을 구성한 샘플들 각각 목표치를 나눠줘야함.
  • 준지도 학습(Semi-supervised learning)
    • 일부는 X와 Y를 모두 가지지만, 나머지는 X만 가진 상황
    • 최근 대부분 데이터가 X 수집은 쉽지만, Y는 수작업이 필요해 최근 중요성 부각

 

다양한 기준에 따른 유형

 

  • 오프라인 학습(offline learning)과 온라인 학습(online learning)
    • 보통은 오프라인 학습을 다룸
    • 온라인 학습은 IOT등에 추가로 발생하는 데이터 샘플을 갖고 점증적 학습 수행
  • 결정론적 학습(Deterministic learning)과 확률적 학습(stochastic learning)
    • 결정론적에서는 같은 데이터를 갖고 다시 학습하면 같은 예측 모델이 만들어진다.
    • 확률적 학습은 학습 과정에서 확률 분포를 사용해 같은 데이터로 다시 학습하면 다른 예측 모델이 만들어짐
  • 분별 모델(Discriminative models)과 생성 모델(Generative models)
    • 분별 모델은 부류 예측에만 관심. 즉, P(y|x)의 추정에 관심
    • 생성 모델은 P(x) 또는 P(x|y)를 추정. 즉, 새로운 샘플 생성 가능

'AI > KDT 인공지능' 카테고리의 다른 글

[06/22] 라이브 세션  (0) 2021.06.22
[06/21] 신경망의 기초  (0) 2021.06.21
[06/15] 분류문제 실습  (0) 2021.06.15
오토인코더, t-SNE  (0) 2021.06.14
[06/02] End to End Machine Learning Project  (0) 2021.06.02

Mnist 데이터 분류

 

# Python ≥3.5 is required
import sys
assert sys.version_info >= (3, 5)

# Scikit-Learn ≥0.20 is required
import sklearn
assert sklearn.__version__ >= "0.20"

# Common imports
import numpy as np
import os

# to make this notebook's output stable across runs
np.random.seed(42)

# To plot pretty figures
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)

# Where to save the figures
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "classification"
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID)
os.makedirs(IMAGES_PATH, exist_ok=True)

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)

MNIST 데이터를 불러오고, 확인해보자.

from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1, cache=True)
mnist.keys()
X, y = mnist["data"], mnist["target"]
print(X.shape) # (70000, 784)
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt

some_digit = X[2]
some_digit_image = some_digit.reshape(28, 28)
plt.imshow(some_digit_image, cmap=mpl.cm.binary)
plt.axis("off")

save_fig("some_digit_plot")
plt.show()

some_digit에는 검은 부분을 제외하고 전부 0인 배열이 나타나게 된다.

y = y.astype(np.uint8)
def plot_digit(data):
    image = data.reshape(28, 28)
    plt.imshow(image, cmap = mpl.cm.binary,
               interpolation="nearest")
    plt.axis("off")
    
def plot_digits(instances, images_per_row=10, **options):
    size = 28
    images_per_row = min(len(instances), images_per_row)
    images = [instance.reshape(size,size) for instance in instances]
    n_rows = (len(instances) - 1) // images_per_row + 1
    row_images = []
    n_empty = n_rows * images_per_row - len(instances)
    images.append(np.zeros((size, size * n_empty)))
    for row in range(n_rows):
        rimages = images[row * images_per_row : (row + 1) * images_per_row]
        row_images.append(np.concatenate(rimages, axis=1))
    image = np.concatenate(row_images, axis=0)
    plt.imshow(image, cmap = mpl.cm.binary, **options)
    plt.axis("off")
plt.figure(figsize=(9,9))
example_images = X[:100]
plot_digits(example_images, images_per_row=10)
save_fig("more_digits_plot")
plt.show()

학습 데이터와 테스트 데이터를 분류하자.

X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]

이진분류기 (Binary classifier)

숫자 5만 식별해보자.

y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)

# 로지스틱 회귀 모델 사용

from sklearn.linear_model import LogisticRegression
log_clf = LogisticRegression(random_state=0).fit(X_train, y_train_5)

log_clf.predict([X[0],X[1],X[2]]) # array([ True, False, False]) #y[0]=5, y[1]=0, y[2]=4이기 때문에 제대로 정답이 나왔다.

# 교차 검증을 사용해 평가

from sklearn.model_selection import cross_val_score
cross_val_score(log_clf, X_train, y_train_5, cv=3, scoring="accuracy") # array([0.97525, 0.97325, 0.9732 ])

모든 교차 검증 폴드에 대해 정확도가 97% 이상이다. 모델이 좋은 것일까?
또 다른 classify를 만들어 보도록 하자. 지금 만들 분류기는 무조건 5가 아니라고 판별하는 함수이다.

from sklearn.base import BaseEstimator
class Never5Classifier(BaseEstimator):
    def fit(self, X, y=None):
        pass
    def predict(self, X):
        return np.zeros(len(X), dtype=bool)
        
never_5_clf = Never5Classifier()
cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring="accuracy") # array([0.91125, 0.90855, 0.90915])

never_5_clf.predict(X) # array([False, False, False, ..., False, False, False])

다 5가 아니라고 판별하는 데에도 불구하고 정확도가 90이 넘게 나온다. 어떻게 이런 결과가 나오는 것일까?

 

숫자 5는 학습 데이터 상에서 10퍼센트 정도의 분포를 차지한다. 그래서 무조건 이것은 5가 아니라고 하면 맞을 확률이 자연스럽게 90퍼센트가 넘게 되는 것이다.

 

이와 비슷한 경우로 1%의 사람에게서만 발병되는 아주 희귀한 병에 대해서 진단을 할 때 관련 모델을 만들면 그 모델이 100%에 대해 그 병이 아니다라고 진단을 내리게 되면 그 진단의 Accuracy는 99%가 되나, 그 모델은 좋은 모델이라고 할 수 없는 것이다. 왜냐하면 그 병을 지닌 사람에 대해서 정확한 진단을 내릴 수 없게 되기 때문이다.

 

즉, 목표값이 불균형인 경우에 정확도는 좋은 지표가 아니다.

 

오차 행렬(Confusion matrix)

 

from sklearn.model_selection import cross_val_predict

y_train_pred = cross_val_predict(log_clf, X_train, y_train_5, cv=3)

y_train_pred.shape # (60000, )

from sklearn.metrics import confusion_matrix

confusion_matrix(y_train_5, y_train_pred)
'''
array([[54039,   540],
       [ 1026,  4395]], dtype=int64)
'''

TN|FP

FN|TP

로 구성되어 있는 오차 행렬이다.

 

 

이 때 정밀도는

Precision = TP/TP+FP

 

재현율은

Recall = TP/TP+FN

이다.

 

즉, 위와 같은 경우에서의 정밀도는

4395/(4395+540)

 

재현율은

4395/(4395+1026)

 

scikit-learn에서 주어진 함수를 통해 정밀도, 재현율을 구해보자.

from sklearn.metrics import precision_score, recall_score

precision_score(y_train_5, y_train_pred) # 0.8905775075987842

4395/(4395+541) # 0.8903970826580226

recall_score(y_train_5, y_train_pred) # 0.8107360265633647

4395/(4395+1026) # 0.8107360265633647

 

그렇다면 모든 답을 5가 아니라고 판별한 모델에 대한 오차 행렬을 구해보자.

confusion_matrix(y_train_5, never_5_clf.predict(X)[:60000])

'''
array([[54579,     0],
       [ 5421,     0]], dtype=int64)
'''

precision_score(y_train_5, never_5_clf.predict(X)[:60000]) # 0

recall_score(y_train_5, never_5_clf.predict(X)[:60000]) # 0

positive 쪽의 답이 전부 0이 나왔다. 그에 따라 자연스럽게 정밀도와 재현율 또한 0이 나오게 된다. 정확도는 90퍼센트로 높게 나왔지만 결과적으론 상당히 좋지 않은 모델이 된 것이다. 

 

그렇다면 어떤 경우에 정밀도가 중요하고, 어떤 경우에 재현율이 중요할까?

병에 대한 진단 모델같은 큰 Risk가 있는 모델의 경우 정밀도보다는 재현율이 높아야 한다.

 

반대의 경우로, 동영상을 분류할 때 어린이들에게 안전한 동영상인지 아닌지 판별하는 알고리즘을 만든다고 할 땐 정밀도가 중요하다고 할 수 있다.

 

Precision / Recall Trade-off

 

 

threshold를 어디에 잡는지에 따라 Precision과 Recall의 값이 완전히 달라질 것이다.

 

y_train_pred[48], y_train_5[48] # (True, False)

some_digit = X_train[48]

y_scores = log_clf.decision_function([some_digit]) # 예측값이 얼마나 정답으로부터 떨어져 있는지 수치로 보여줌.
y_scores # array([0.22419046])
some_digit_image = some_digit.reshape(28, 28)
plt.imshow(some_digit_image, cmap=mpl.cm.binary)
plt.axis("off")

save_fig("some_digit_plot")
plt.show()

threshold = 0
y_some_digit_pred = (y_scores > threshold)
y_some_digit_pred # array([ True])

threshold = 0.5
y_some_digit_pred = (y_scores > threshold)
y_some_digit_pred # array([False]) 

한 경우에 대해 threshold에 따라서 recall을 줄일 수도 (threshold가 클수록) 있다. 이런 식으로 recall과 precision의 비율을 조절할 수 있는 것이다.

y_scores = cross_val_predict(log_clf, X_train, y_train_5, cv=3,
                             method="decision_function")
                             
y_scores.shape # (60000,)

from sklearn.metrics import precision_recall_curve

precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)

precisions.shape # (59897,) # 각 threshold에 따른 precision의 값들

thresholds.shape # (59896,) # 가능한 모든 경우의 threshold의 값들

 

precision과 recall을 그래프로 나타낼 수 있다.

def plot_precision_vs_recall(precisions, recalls):
    plt.plot(recalls, precisions, "b-", linewidth=2)
    plt.xlabel("Recall", fontsize=16)
    plt.ylabel("Precision", fontsize=16)
    plt.axis([0, 1, 0, 1])
    plt.grid(True)

plt.figure(figsize=(8, 6))
plot_precision_vs_recall(precisions, recalls)
save_fig("precision_vs_recall_plot")
plt.show()


다중 분류 (Multicalss Classification)

 

지금까지 MNIST 문제를 이진 분류해보았다. 이번엔 원래의 MNIST 분류 문제의 목적에 맞게 다중 분류를 해보도록 하자.

 

from sklearn.linear_model import LogisticRegression
softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10) # multinomial로 설정하면 multiclass에 대한 logisticregression이 가능
softmax_reg.fit(X_train, y_train)

softmax_reg.predict(X_train)[:10] # array([5, 0, 4, 1, 9, 2, 1, 3, 1, 4], dtype=uint8) # 정확히 예측하고 있다.

from sklearn.metrics import accuracy_score
y_pred = softmax_reg.predict(X_test)
accuracy_score(y_test, y_pred) # 0.9243

 

위의 모델을 조금 더 향상시키도록 하자.

 

Data Augmentation

 

가지고 있는 학습데이터에 레이블을 유지한 채 약간의 변형을 가해 데이터를 더하여 모델을 새로 학습했을 때 조금 더 안정적인 모델을 만들어낼 수 있을 것이다.

 

from scipy.ndimage.interpolation import shift

# 오른쪽이나 아래로 이미지를 조금씩 shift시키는 함수
def shift_image(image, dx, dy):
    image = image.reshape((28, 28))
    shifted_image = shift(image, [dy, dx], cval=0, mode="constant")
    return shifted_image.reshape([-1])
    
image = X_train[1000]
shifted_image_down = shift_image(image, 0, 5) # 아래쪽으로 이동
shifted_image_left = shift_image(image, -5, 0) # 왼쪽으로 이동

plt.figure(figsize=(12,3))
plt.subplot(131)
plt.title("Original", fontsize=14)
plt.imshow(image.reshape(28, 28), interpolation="nearest", cmap="Greys")
plt.subplot(132)
plt.title("Shifted down", fontsize=14)
plt.imshow(shifted_image_down.reshape(28, 28), interpolation="nearest", cmap="Greys")
plt.subplot(133)
plt.title("Shifted left", fontsize=14)
plt.imshow(shifted_image_left.reshape(28, 28), interpolation="nearest", cmap="Greys")
plt.show()

X_train_augmented = [image for image in X_train]
y_train_augmented = [label for label in y_train]

# 레이블을 유지한 채 shift한 데이터를 추가하는 작업
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
    for image, label in zip(X_train, y_train):
        X_train_augmented.append(shift_image(image, dx, dy)) 
        y_train_augmented.append(label)

X_train_augmented = np.array(X_train_augmented)
y_train_augmented = np.array(y_train_augmented)

X_train_augmented.shape # (300000, 784) # 원래의 데이터보다 5배만큼 늘어났다.

# 같은 레이블의 데이터가 연속으로 있으면 모델을 학습하는 데 있어서 좋지 않은 영향을 끼칠 것이다. 그래서 데이터를 섞어주는 작업을 하자.
shuffle_idx = np.random.permutation(len(X_train_augmented))
X_train_augmented = X_train_augmented[shuffle_idx]
y_train_augmented = y_train_augmented[shuffle_idx]

# 모델 학습
softmax_reg_augmented = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10)
softmax_reg_augmented.fit(X_train_augmented, y_train_augmented)

y_pred = softmax_reg_augmented.predict(X_test)
accuracy_score(y_test, y_pred) # 0.9279 # data augmentation을 진행하기 전보다 0.002정도 오른 것을 확인할 수 있다.
# 0.002면 작은 수치일 수도 있으나, 이미 잘 나온 모델에서 조금이라도 정확도를 올렸다는 것은 굉장히 유의미한 일이다.

Titanic 데이터셋에 대해 분류하기

 

import numpy as np
import pandas as pd

train_data = pd.read_csv("titanic.csv")

 

속성들

  • Survived: that's the target, 0 means the passenger did not survive, while 1 means he/she survived.
  • Pclass: passenger class.
  • Name, Sex, Age: self-explanatory
  • SibSp: how many siblings & spouses of the passenger aboard the Titanic.
  • Parch: how many children & parents of the passenger aboard the Titanic.
  • Ticket: ticket id
  • Fare: price paid (in pounds)
  • Cabin: passenger's cabin number
  • Embarked: where the passenger embarked the Titanic
train_data.info()
'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
'''

Age, Cabin, Embarked 속성들이 missing value를 갖고 있다.

Cabin, Name, Ticket 속성은 무시하도록 하자.

이 중 Ticket같은 경우는 고유한 번호가 될 가능성이 높은데 고유한 식별자를 feature data로 쓰면 학습을 할 때 고유한 정보를 외우는 수준까지 갈 수도 있기 때문에(이 고유한 식별자에 집중하게 될 수도 있기 때문에) 예측값이 굉장히 안 좋아질 수도 있다. 그렇기 때문에 사용하지 않는 것이 더 좋다고 볼 수 있다.

train_data["Survived"].value_counts()
'''
0    549
1    342
Name: Survived, dtype: int64
'''
train_data["Pclass"].value_counts()
'''
3    491
1    216
2    184
Name: Pclass, dtype: int64
'''
train_data["Sex"].value_counts()
'''
male      577
female    314
Name: Sex, dtype: int64
'''
train_data["Embarked"].value_counts()
'''
S    644
C    168
Q     77
Name: Embarked, dtype: int64
'''
from sklearn.base import BaseEstimator, TransformerMixin

# 속성을 골라 사용할 수 있도록 해줌
class DataFrameSelector(BaseEstimator, TransformerMixin):
    def __init__(self, attribute_names):
        self.attribute_names = attribute_names
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        return X[self.attribute_names]
      
# Numerical 속성 처리 Pipeline      
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

num_pipeline = Pipeline([
        ("select_numeric", DataFrameSelector(["Age", "SibSp", "Parch", "Fare"])),
        ("imputer", SimpleImputer(strategy="median")),
    ])
    

# missing value를 가장 많이 나오는 값으로 채워넣어준다.
class MostFrequentImputer(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        self.most_frequent_ = pd.Series([X[c].value_counts().index[0] for c in X],
                                        index=X.columns)
        return self
    def transform(self, X, y=None):
        return X.fillna(self.most_frequent_)

# Categorical 속성 처리 Pipeline
from sklearn.preprocessing import OneHotEncoder
cat_pipeline = Pipeline([
        ("select_cat", DataFrameSelector(["Pclass", "Sex", "Embarked"])),
        ("imputer", MostFrequentImputer()),
        ("cat_encoder", OneHotEncoder(sparse=False)),
    ])

# Categorical, Numerical 속성들을 통합하자.
from sklearn.pipeline import FeatureUnion
preprocess_pipeline = FeatureUnion(transformer_list=[
        ("num_pipeline", num_pipeline),
        ("cat_pipeline", cat_pipeline),
    ])

# 최종적으로 만들어진 pipeline을 train_data에 적용시켜보자.
X_train = preprocess_pipeline.fit_transform(train_data)
X_train.shape # (891, 12)

# 목표값 벡터
y_train = train_data["Survived"]

log_clf = LogisticRegression(random_state=0).fit(X_train, y_train)

# 모델에서 어떤 통찰을 얻을 수 있는지 살펴보기
a = np.c_[log_clf.decision_function(X_train), y_train, X_train] # np.c_는 1차원 배열을 칼럼으로 붙여 2차원 배열로 만드는 것이다.
df = pd.DataFrame(data=a, columns=["Score", "Survived", "Age", "SibSp", "Parch", "Fare", "Pclass_1", "Pclass_2", "Pclass_3", "Female", "Male", "Embarked_C", "Embarked_Q", "Embarked_S"])
df.sort_values(by=['Score'], ascending=False)[:20]

df.sort_values(by=['Score'])[:20]

 

'AI > KDT 인공지능' 카테고리의 다른 글

[06/21] 신경망의 기초  (0) 2021.06.21
[06/16] 인공지능과 기계학습  (0) 2021.06.16
오토인코더, t-SNE  (0) 2021.06.14
[06/02] End to End Machine Learning Project  (0) 2021.06.02
[05/18] Django로 동적 웹페이지 만들기  (0) 2021.05.18

+ Recent posts