ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [08.03] Day2 - 'Python과 딥러닝 기초'😮
    네이버 부스트캠프 AI Tech 2기 2021. 8. 6. 22:00
    728x90
    반응형

    📖 Python 2강(변수, 함수, 조건문, String, etc..)

    Python 강의는 기본적인 것은 어느정도 알고 있기 때문에, 중요한 개념에 대한 것만 정리해 놓겠다! 👨🏻‍💻

    강사 : 최성철 교수님

    [배운 점]

    변수는 메모리 주소를 가지고 있고 변수에 들어가는 값은 메모리 주소에 할당된다.(물리적으로 할당)

    → DRAM어딘가에 저장이 되어버린다.

    Python 같은 경우는 카맬케이스가 아니라 Snake_case를 사용한다!

    변수명은 대소문자를 구분한다.

    Data Type (각 타입별로 차지하는 메모리 공간이 다르다.)

    • integer : 정수형
    • float : 실수형
    • string : 문자형 ('/'가 들어가 있다.)
    • boolean : 참/거짓

    파이썬의 장점 : 이런 Data Type이 프로그램이 실행하는 시점에 결정이 되는 Dynamic Typing언어이다.

    실수형 → 정수형으로 Type Casting하면 내림이 된다!

    문자형(숫자) → 정수/실수형으로 바꿀 수 있다.

    List

    시퀀스형 자료형, 여러 데이터들의 집합

    int, float, string 등등 여러개를 담아둘 수 있다.

    안에 있는 값은 각각 주소를 가지고 이는 index로 접근한다.

    List같은 경우는 Slicing이 가능하다. [시작 인덱스: 끝 인덱스 : 몇칸씩 뛸 것인가]

    ex) list[1: 8] → 1번 index위치부터 7번째 index위치까지 자른다.(list[::-1] → 역슬라이싱, 거꾸로)

    concatnation ( + : list 를 붙혀준다, * : 여러번찍힌다., extend : 이어붙힌다.)

    remove : 가장 처음 맞는 원소를 지운다.

    del : 메모리에서 삭제한다.

    Python에 메모리 저장 방식

    a = [1,2,3,4,5]

    b = [6,7,8,9,10]

    이렇게 선언하면 각각 메모리 공간을 가지는데,

    b = a

    라고 하면 b 가 a 를 가리킨다. (같은 메모리 주소를 가르킨다.)

    복사하고 싶다? : ex ) b = a[:](얘는 1 차원만 가능한다.) 이런식으로 or copy함수를 사용한다.

    import copy
    
    #완전히 복사
    새로운 객체 = copy.deepcopy(복사할 객체)

    함수

    : 함수는 어떤 일을 수행하는 코드 덩어리라는 의미이다. 반복적 수행을 하나로 정리해서 필요할 때 호출하면 깔끔하게 코드를 작성할 수 있다.

    def 함수 이름(Parameter):
        return 반환할 값
    
    함수 이름(Argument)
    
    #반환값이 있는가? 없는가? 를 잘 생각
    #Parameter가 있는가? 없는가? 잘 생각

    Shell에서 Python 파일 실행

    → $python 파이썬파일이름.py

    #출력 formatting
    print('%s %s' % ('one','two')) -> 데이터 타입에 맞는 형식만 받는다.
    print('{} {}'.format('one', two)) -> 알아서 타입을 지정해줌
    #print('hello {0}, weight : {1:10.3f}'.formate(name, wei))
    -> name 들어가고 weight는 10칸잡고 소수점 3자리까지만( < : 왼쪽 정렬, > : 오른쪽 정렬)
    
    #f-string
    name = 'jay', age = 25
    print(f"Hello, {name}. Age, {age}.") #name, age 변수가 바로 들어감.

    Bit, Byte

    컴퓨터는 2진수로 데이터를 저장하고, 이진수 한자리는 1bit로 저장된다.(0 or 1)

    1byte = 8bit(256가지 정보를 저장할 수 있다.)

    컴퓨터가 문자를 처리할때는 숫자로 변환해서 처리하며 우리나라는 UTF-8이 표준이다.

    int : 4byte

    long : 무제한

    float : 8byte

    String

    각 문자는 offset으로 접근한다. Index를 통해서 할당된 값을 가져오는 것이 인덱싱이라고 부른다.

    slicing을 표현할 수 있다.

    ex) 'hello'[:3] → 'hel'

    '+' 연산을 사용해서 연결도 가능하다.

    String의 여러가지 함수들

    Parameter 넘기는 방식

    1. Call by value : 함수에 인자를 넘길때 값만 넘김
    2. Call by ref : 함수에 인자를 넘길때 메모리 주소를 넘김(객체의 주소가 넘어간다.)

    Recursive Function

    : 자기자신을 호출하는 함수, 점화식 같은 재귀적 수학 모형에 사용

    조건

    1. 재귀 종료 조건
    2. 종료 조건까지 함수호출 반복

    Defaultdict

    • Dict type 값에 기본 값을 지정, 신규값 생성시 사용하는 방법
    from collections import defaultdict
    변수 = defaultdict(lambda : 0)

    Counter

    • Sequence type의 data element 들의 갯수를 dict 형태로 반환
    from collections import Counter
    
    A = ['a','b','a','c']
    -> Counter({'a' : 2, 'b' : 1, 'c': 1})
    
    덧셈, 뺄셈도 응용할 수 있음.

    Pythonic Code

    Why?

    1. 남에 코드를 이해하기 위해!
    2. 효율적으로 코드를 짜기 위해
    3. 간지남 🥴

    1. Split 함수 & Join 함수

    '문자열'.split() → 빈칸을 기준으로 문자를 나눈다! 안에 다양한 자를 기준을 넣어서 자를 수있다.

    ' '.join(list) → list를 합쳐버린다.

    2. List comprehension

    • 기존 list를 간단히 다른 list를 만드는 기법
    • 파이썬에서 가장 많이사용하는 문법중 하나
    H = [i for i in range(10)]
    ##
    
    E = [i for i in range(10) if i % 2 == 0 ]
    ##
    
    L = [[i, j] for i in A for j in B]
    ##
    for i in A:
        for j in B:
            [i,j]
    
    O = [[i+j] for i in A] for j in B]
    ##
    뒤에 for loop부터 동작

    3. enumerate(list)

    : for index, value in enumerate(list) → index와 value가 같이 나온다.

    4. zip(list, list)

    : 두개의 list를 같은 위치에 있는 값을 묶어서 병렬적으로 추출해준다.

    return (Tuple)

    5. lambda, map, reduce

    def f(x,y):
        return x + y
    
    -> f = (lambda x, y : x + y) #람다는 많이 쓰지만, 권장하지는 않는다!
    f(100, 500)
    => 600
    
    ###
    많이 않쓰는 이유
        1. 어려운 문법
        2. 테스트의 어려움
        3. Docstring 지원이 미비하다
        4. 코드 해석이 어렵다
        5. 이름이 존재하지 않는 함수이다.
    ###
    ========================================================================
    ex)
    hello = ['1','2, '3']
    
    hello = list(map(int, hello))
    -> 전체를 int로 매핑해준다.
    변환해줄때 lambda도 적용할 수 있다.
    ex)
    hello = list(map(lambda x: x*2, hello))
    
    ========================================================================
    from functools import reduce
    reduce(lambda x, y : x + y, [1,2,3,4,5])

    [회고]

    Vs Codedptj 'Python DocString Generator'를 플러그인해서 받으면 함수에 대한 DocString을 자동으로 입력해준다! 코드의 가독성을 높히는데 Very Good!

    함수 개발 가이드라인(Clean Code)

    1. 가능한 짧게 작성
    2. 함수 이름에 역할, 의도가 명확히 쓴다.
    3. 하나의 함수에 유사한 역할을 하는 코드만 포함한다.
    4. 인자로 받은 값 자체는 바꾸지 않는 것이 좋다. → 복사 형태로 만들어놓고 다뤄라
    5. 공통적으로 사용하는 부분을 함수로 만든다.
    6. 복잡한 수식은 함수로 만든다.
    7. 복잡한 조건은 식별 가능한 이름의 함수로 만든다.

    🤩 코딩은 내가 혼자 짜는 것이 아닌 팀과 함께 짜는 것이기 때문에 '사람이 이해할 수 있는 코드'를 짠다!

    → 규칙 '코딩 컨벤션'

    Python에서 iterable함수를 리스트에 씌우면 아직 메모리에 생성하는 것이 아니다. 링크드리스트 형식으로 객체를 가르키면서 저장하는 것 같다.

    Generator 는 element 가 사용되는 시점에 값을 메모리에 반환해 준다.

    : yield 라는 예약어를 통해서 활용하며, Generator같은 경우는 메모리를 효율적으로 활용할 수 있다.

    파일 데이터, 큰 데이터를 처리할때 Generator를 사용하는 것이 좋다.

    가변인자 asterisk

    : Asterisk(*) 를 사용해 함수의 파라미터를 표시한다.

    (ex args)는 여러개의 파라미터를 받을 수 있다. 이는 *Tuple타입**으로 들어간다.

    키워드 가변인자

    : Asterisk(*)를 2개를 사용해서 함수의 파라미터를 표시한다.

    (ex kwargs) 여러개의 파라미터를 받으면 **Dict 타입으로 받는다.

    def test(one, two=10, *args, **kwargs):
        print(one+two+sum(args))
        print(args)
        pirnt(kwargs)
    test(1,2,3,4,5,6, ten=10, eleven =11)
    
    -> 1, 2,(3,4,5,6),{ten:10, elevne:11}

    📖 딥러닝 학습 방법 이해하기(AI Math 5강)

    [수업 내용]

    강사님 : 임성빈 교수님

    이전 시간까지는 데이터들의 선형 회귀식을 구하는 과정을 경사하강법으로 구했었다.

    그렇지만 이런 선형 모델은 단순한 유형들에는 괜찮지만, 더 복잡한 패턴들을 푸는 것은 선형 모델로는 한계가 있다.

    → 그래서 비선형모델인 신경망(Neural Network)을 배운다.

    데이터를 모아놓은 행렬 X와 다른 차원으로 보내주는 가중치 행렬 W, b 행렬은 bias를 의미하며 y절편에 해당하고, 각 행들이 모두 같은 값이다.

    처음 d 차원이었던 입력 벡터에서 p 차원인 출력 벡터로 바뀐다는 것을 명심한다!

    화살표는 가중치 행렬을 의미하고 입력 데이터들 D개와 출력 데이터들 P개를 맞춰주기 위해서 dxp만큼의 가중치 행렬을 가져야 한다.

    Softmax 연산자

    : 모델의 출력을 확률로 해석할 수 있게 변환해주는 함수

    분류 문제로 많이 풀며, 주어진 데이터가 어떤 클래스에 속할 확률이 얼마인지를 구할 수 있다. 그래서 현재 모델에서 특정 클래스에 속하는 모델을 sofmax로 구한다.

    #numpy로 softmax로 구한 것
    def softmax(vector):
        denumerator = np.exp(vector - np.max(vector, axis=-1, keepdims= True))
        numerator = np.sum(denumerator, axis=-1, keepdims = True)
        return denumerator / numerator
    
    #np.max -> softmax 함수가 지수연산을 쓰기 때문에 너무 큰수가들어오면 overflow가 발생해서 적용하는 것이다.

    학습에서는 softmax를 사용하지만, 추론에서는 one-hot 벡터를 이용해 최대값을 가진 주소만 1로 출력하는 방법으로 사용한다.

    이렇게 마지막 단에서 softmax같은 비선형 함수를 섞어줌으로써, 선형 함수로 나오는 출력물을 비선형모델로 바꿔주게 된다. (필요에따라 여러가지 activation function을 사용한다.)

    이런 활성함수로 비선형함수로 잠재 벡터를 만들고 이를 '뉴런'이라고 하고 이런 Network를 '신경망'이라고 한다.

    여러가지 Activation Function

    Sigmoid, tanh 함수는 전통적으로 많이 쓰이는 활성함수지만, 오늘날에서는 Relu함수를 많이 사용한다.

    신경망 : 선형모델 + 활성함수

    이렇게 잠재 벡터가 또다른 Layer의 Input으로 들어간다. 이는 2Layer를 표현하고 있다.

    딥러닝은 이런 구조로 기본적인 형태를 이룬다.

    MLP(다층 퍼셈트론)

    Forward-Propagation

    이렇게 하나의 신경망이 아닌 여러개의 신경망이 쌓인 모델을 MLP라고 부르며 O 까지의 진행을 forward propagation 이라고 부릅니다.

    ⭐️ Back-Propagation

    역전파 알고리즘으로 각 Layer의 가중치 행렬, bias를 학습한다.

    손실함수 L 을 정의한다. 각각의 가중치 행렬 w(l)에 대해 손실함수에 대한 미분을 계산할 때 역전파 알고리즘을 사용한다. (Gradient를 계산한다.)

    방법 : 각층의 Gradient Vector를 위에서 부터 역순으로 게산한다. 그리고 이는 위에부터 연쇄법칙을 통해 Gradient Vector를 전달한다.

    ✍️ 손으로 해보기

    2층 신경망에서 Back-Propagation

    문제 : W1에 대한 손실함수 L의 경사하강법을 쓰고 싶다. (W1은 행렬이라 각 성분에 대한 편미분을 구해야 한다.

    [회고]

    Relu는 비선형? 선형? : 이 함수는 전형적 비선형 함수이다.

    왜 여러개 쌓나? : 층이 깊으면 목적함수를 근사하는데 필요한 뉴런(노드)의 수가 줄어들어 효율적인 학습이 가능하다.

    각각의 뉴런은 텐서로 표현하는데, Back-Propagation을 계산할때 각 텐서 값을 미리 메모리에 저장해야만 가능하다.(더 계산양이 많다, 미분을 해야하기 때문에)

    선형 모델에 대해서 비선형성을 부여하기 위해서 Activation function을 적용한다는 개념을 배웠다. 그래서 Neural Network 같은 신경망은 더 복잡한 Non-Convex 형태의 그래프에서 최적의 해를 정확히 찾아갈 수 있다고 생각이 된다.

    좀더 근본적으로 각 Activation Function에 대해서 어떨때 장점과 단점이 있는지 정리를 해봐야겠다. 그리고 BackPropagation에서 어떤 식으로 가중치를 수정하는지 손으로 한번쯤은 해볼만 한 것같다.

    [궁금한 점]

    그런데 층이 깊으면 가중치가 더 많아 질텐데, 가중치가 많아진다는 것은 학습할 파라미터가 많아지는 것이고 그러면 연산량이 더 많은 것이 아닌가?

    BackPropagation이 진행되는 동안 Gradient Vector들을 저장해 놓는데, 나중에 ForwardPropagation이 진행될때 가중치 행렬들을 수정하고 메모리 효율을 위해서 초기화하는가?


    ♾ 확률론 맛보기(AI Math 6강)

    [수업 내용]

    강사 : 임성빈 교수님

    확률론이 딥러닝에서 필요한 이유?

    : ML에서 사용되는 Loss function들의 작동 원리는 데이터 공간을 통계적으로 해석해서 유도하기 때문

    회귀 - L2 norm은 예측오차의 분산을 가장 최소화하는 방향으로 학습을 유도

    분류 - Cross-entropy 는 모델 예측의 불확실성을 최소화하는 방향으로 학습을 유도

    확률 변수는 D에 따라서 이산형, 연속형으로 구분한다.

    1. 이산형 확률 변수

    확률변수 X가 가질 수 있는 경우의 수를 모두 고려해서 확률을 더해 모델링한다.

    1. 연속형 확률 변수

    : 데이터 공간에 정의된 확률변수의 밀도 위에서의 적분을 통해 모델링한다.

    이런 P와 같은 밀도는 적분을 통해서 계산해야한다.

    연속형 확률 변수일것 같지만 이렇게 결합분포로 산정해서 표현하면 이산형으로 볼 수 있다.(거꾸로도 가능하다. 이는 모델링에 따라서 달라진다.)

    1. P(x) 는 주변 확률분포라고 부르며 P(x,y)에서 유도 된다. y의 값에 상관없이 x로 나눠진다는 것으로 보인다.
    2. 또한 ⭐️ 조건부 확률분포 P(x/y)도 구할 수 있다. 이는 데이터 공간에서 입력 x와 출력 y와의 관계를 모델링한다. → 이 조건부확률분포는 특정 클래스가 주어진 조건에서 데이터의 확률분포를 보여준다.Softmax와 선형모델의 결합으로 데이터로부터 추출된 패턴을 기반으로 확률을 해석하는데 사용한다.
    3. 조건부 확률은 입력변수 x에 대해 정답이 y일 확률을 의미한다.(연속확률변수에서는 확률이 아니고 밀도로 해석한다.)

    기대값이란?

    : 데이터를 대표하는 통계량.(평균이라고 많이 배웠다.)

    연속확률분포 - 주어진 함수에 확률 밀도함수를 곱해서 적분한다.

    이산확률분포 - 주어진 함수에 확률 질량함수를 곱해서 급수를 구한다.

    → 이런 기대값을 이용해서 분산, 첨도, 공분산 등을 구할 수 있다.

    Monte Carlo 샘플링

    : 확률분포를 모를때, 데이터를 이용해 기대값을 계산하기 위해서

     

    함수 f에 샘플링한 데이터를 대입하고 이 데이터들의 산술 평균값이 우리가 구할 기대값과 유사하게 된다.(연속형, 이산형에 따라 상관없다.)

    주의! 샘플링하는 분포에서 독립적으로 샘플링해야만 몬테카를로 샘플링이 동작한다. 이런 독립추출만 보장하면 대수의 법칙으로 수렴성을 보장한다.

    [회고]

    이산형인지 연속형인지는 확률변수의 분포 D에 의해 결정된다.

    모든 확률 변수가 이산형, 연속형으로 표현되는 것은 아니다!

    회귀 문제에서 조건부 기대값을 사용하는 이유? : L2-Norm을 최소화하는 함수와 일치해서!

    반응형
Designed by Tistory.