강의 출처 : 패스트캠퍼스 한 번에 끝내는 컴퓨터 공학 전공 필수 & 인공지능 심화 초격차 패키지 Online

Part1. 파이썬 위주 프로그래밍 기초

패스트 캠퍼스 컴퓨터 공학 전공 필수 강의를 이제 막 듣기 시작하였다. Part 1 은 파이썬 위주의 프로그래밍 기초 내용이 나와있다. 파이썬 언어에 어느정도 익숙해서 효율을 위해 Ch07. 상속과 예외처리, Ch09. 병렬처리, Ch10. DB연동과 정규식, Ch12. Rest API 와 Flask, Ch13. 파이썬 속도 문제 부분만 들으며 복습해보았다.

Ch07. 상속과 예외처리

상속 : 한 클래스 (;자식 클래스) 가 다른 클래스 (;부모 클래스) 로부터 데이터 속성과 메소드를 물려받는 것.

overriding : 부모 클래스 내에 a 라는 메소드가 있었고 자식 클래스가 부모 클래스를 물려받는다면 자연스럽게 자식 클래스에도 부모 클래스에서 정의되었던 a라는 메소드가 생긴다. 이 때 자식 클래스에 a 라는 메소드를 새롭게 정의하면 a 라는 메소드는 overriding 되어서 새롭게 정의된 메소드로 사용된다.

<출처 : 파이썬 코딩 도장 36.3강>

class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = '안녕하세요.'
 
class Student(Person):
    def __init__(self):
        print('Student __init__')
        self.school = '파이썬 코딩 도장'
 
james = Student()
print(james.school)
print(james.hello)    # 기반 클래스의 속성을 출력하려고 하면 에러가 발생함

위의 예시에서도 자식 클래스인 Student 에서 _init_ 을 새로 정의했기 때문에 overriding 되었다.

super : 부모 클래스의 호출

  • 파이썬 3.x 버전 : super().부모클래스의 메소드(self)
  • 파이썬 2x 버전 (3점대 버전에서도 사용 가능) : super(자식클래스,self).부모클래스의 메소드()
class add_calculator:
  def addition(self,x,y):
    print(x+y)
class good_caculator(add_calculator):
  def addition2(self,x,y):
    super().addition(x,y)

다중상속 : 여러 클래스들로부터 동시에 상속받는 것도 가능하다.

ex. class C(A,B):

이 때, A 에 있는 메소드와 B 에 있는 메소드의 명칭이 같다면 (=이름이 겹친다면) 먼저 입력한 A 의 메소드로 상속받는다.

딥러닝에 이용되는 상속 개념

class Net(nn.Module)
	def __init__(self):
    ...

pytorch 에서 모델을 짤 때도 기본적으로 상속 개념이 활용된다. nn.Module 은 모든 뉴럴 네트워크 모듈의 기본 클래스이다. (Layer : Model 또는 Module 을 구성하는 한 개의 층. Module : 1개 이상의 layer 가 모여서 구성된 것. Module 이 모여서 새로운 Module 을 만들 수 있음. Model : 최종적인 학습을 시킬 모델. 1개의 모듈일 수도 있음)

이 때 nn.Module 의 _init_

		self.training = True
    self._parameters = OrderedDict()
    self._buffers = OrderedDict()
    self._backward_hooks = OrderedDict()
    self._forward_hooks = OrderedDict()
    self._forward_pre_hooks = OrderedDict()
    self._state_dict_hooks = OrderedDict()
    self._load_state_dict_pre_hooks = OrderedDict()
    self._modules = OrderedDict()

와 같은 속성들이 정의되어있다.

그리고 self.linear = nn.Linear(…) 같은 방식으로 모듈 내 layer 을 추가해주면, 파이토치 세계관에서는 자동으로 __setattr__메소드를 불러온다. 해당 메소드는

def __setattr__(self, name: str, value: Union[Tensor, 'Module']) -> None:
    # [...]
    modules = self.__dict__.get('_modules')
    if isinstance(value, Module):
        if modules is None:
            raise AttributeError("cannot assign module before Module.__init__() call")
        remove_from(self.__dict__, self._parameters, self._buffers, self._non_persistent_buffers_set)
        modules[name] = value

이런 식으로 구성되어있는데, 즉 부모 클래스인 nn.Module 에 있는 self._modules 속성 (;dict 자료형)을 불러와서 사용자가 새로 짠 레이어를 여기에 실제로 추가해주는 방식이다. 따라서 정리하자면 토치 내에서 Net 이라는 모듈을 짜고 싶은데 Net 안에 어떠한 레이어를 넣어주려면 __setattr__ 메소드가 소환되고, 해당 메소드는 self._modules 내에 사용자가 추가한 레이어를 입력해주는 역할을 하기 때문에 __setattr__ 메소드를 제대로 작동시키기 위해서는 부모 클래스인 nn.Module 내에 존재하는 self._modules 등 기본 attributes 을 자식 클래스인 Net에서도 사용 가능하도록 미리 불러와서 초기화시켜야한다.

/

이후 추상클래스와 isinstance 메소드는 강사님이 사실 상속 챕터에 속하진 않는데 어디에 넣을지 몰라서 같이 추가하였다고 한다.

추상클래스 : “하위 클래스들에게 강제로 특정 메소드를 만들게 하라 !”

사용 방법 및 특징:

  • 추상 클래스는 abc 모듈의 ABCMeta 클래스를 상속받아 만든다. 이 때 반드시 metaclass=메타클래스이름 의 형태로 상속받는다.
  • 추상 메소드라는 @abstractmethod 데코레이터를 사용하여 자신의 하위 객체에게 특정 메소드의 생성을 강제할 수 있다.
  • 추상 클래스는 자신의 객체를 생성할 수 없다.
  • 추상 메소드는 이름만 존재하고 내용은 없다.

ex.

KakaoTalk_Photo_2021-12-09-10-19-29

isinstance : isintance(변수,클래스 이름) 은 주어진 변수의 값이 클래스의 인스턴스인지 여부를 반환해주는 함수

a=3
isinstance(a,int)
>> True

/

Try ~ except

try ~ except 의 경우, 실제 코드를 짤 때 표 형식의 데이터에서 서술형 답변을 모두 결측치로 처리하기 위해서 try: int(a라는 문장), except: 결측치 처리, 이런 식으로 사용하였다. 그런데 else,finally 이런 조건문과도 같이 세트로 사용할 수 있다는 사실은 새롭게 알게 되었다.

try:
  에러 문장
except:
  에러났을  실행할 문장
else:
  에러가  나면 실행할 문장
finally:
  에러 발생 여부와 상관없이 실행될 문장 

예외의 강제 발생

raise Exception("강제로 에러를 발생시킴")

Assert 문 : assert 로 시작하는 문장에 조건식을 적으면, 조건을 만족하지 않을 경우 error 가 발생하며 우측의 string 을 출력한다.

A=3
assert A>10,'A가 너무 작습니다'

Ch09. 병렬처리

이후 ‘컴퓨터 구조’ 파트에서 더 자세하게 배울 수 있겠지만 우선 병렬처리를 이해하는 데도 간단하게는 ‘프로세스’ 와 ‘모메리’ 의 개념을 알아야할 것 같아서 매우 재미있게 쓰여진 ‘비전공자를 위한 이해할 수 있는 IT지식’ 이라는 책을 참고하였다.

스크린샷 2021-12-09 오전 10 35 42

내가 간단히 이해한 바로는 CPU 는 실제 작업을 수행하는 컴퓨터의 머리이지만, 기억력은 없다. 따라서 ‘기억력’ 을 담당하는 CPU 의 창고가 기억장치인 HDD(하드디스크),SSD 이다. 하지만 이 거대한 창고에서 그 때 그 때 필요한 데이터를 찾는 데에는 시간이 너무 오래 걸린다. 기억 장치가 빠른 두뇌회전 속도를 따라잡지 못하는 셈이다. 그래서 RAM 이라는 CPU 의 개인작업공간을 새로 만들었다. 작업이 필요한 큰 데이터 뭉치를 보조기억장치에서 메모리로 한 번 옮겨놓고, 메모리 안에서만 작업을 하는 것이다.

cpu내 물리적 연산부가 코어고 코어의 효율을 향상시키기위해 각 코어당 분산처리할 수 있는 기술(=하이퍼스레딩)이 나왔습니다. 엄밀히 따지면 하나의 코어가 여러 작업을 분할하여 빠르게 처리하는것이고 이를 나누었을때 작업의 단위를 스레드라고 칭합니다. 예로 1111111 이란 작업과 000000 이란 작업이 있으면 1코어당 1스레드의 경우 1111111 000000 으로 처리하지만 1코어당 2스레드의 경우 101010101010 처럼 일을 처리하기때문에 마치 코어가 2개인것 처럼 보이는것이죠. 코어,스레드

코어 : 칩에 물리적으로 존재하는 연산부

스레드 : 실제 os 에서 인식하고 작동하는 작업 단위

파이썬의 쓰레드 : 파이썬은 default 로 싱글 쓰레드에서 순차적으로 동작한다. 따라서 병렬처리를 위해선 별도의 모듈을 사용하여 수행해야한다. -> threading 모듈

from threading import Thread

def work(work_id,start,end,result):
  total=0
  for i in range(start,end):
    total+=i
  result.append(total)
if __name__=='__main__':
  result=[]
  th1=Thread(target=work,args=(1,0,10000,result))
  th2=Thread(target=work,args=(2,10001,20000,result))
  
  th1.start()
  th2.start()
  th1.join()
  th2.join()
  
  print(sum(result))

이렇게 실행시키면 쓰레드 2개에서 병렬적으로 작업을 수행하면서 result 에는 [th1 결과물, th2 결과물] 이 나온다.

하지만, 파이썬의 GIL 이라는 정책 때문에 cpu 에서 작업을 할 때는 멀티 쓰레드가 작동하지 않는다고 한다. 위 코드도 강사님이 직접 이렇게 threading 을 썼음에도 불구하고 시간 단축이 안 됐음을 보여주었다. (파일 입출력과 같이 하드디스크를 사용하는 경우 cpu 가 아니기 때문에 멀티 쓰레드가 가능하다고 한다.)

하지만, 여전히 할 수 있는 ‘multiprocessing’ 이라는 모듈을 사용하는 방법이 있다.

1) pool : 처리할 일꾼들 개수를 지정하고 알아서 너네끼리 나눠서 작업해봐 !

from multiprocessing import Pool

def f(x):
  return x*x

if __name__ == '__main__':
  p=Pool(4)
  result=p.map(f,[1,2,3,4])
  p.close()
  print(result) # [1,4,9,16]

2) process : 각 프로세스별 할당량을 명시적으로 적어두고 그걸 처리하게 함

import os
from multiprocessing import Process

def f(x):
  print(x*x)
if __name__ == '__main__':
  numbers=[1,2]
  proc1=Process(target=f,args=(numbers[0],))
  proc1.start()
  proc2=Process(target=f,args=(numbers[1],))
  proc2.start()
  proc1.join()
  proc2.join()

사실 완벽하게는 이해하지 못했다. 이후 다른 cs 기초 파트를 듣고 나면 더 이해가 쉬울 것 같다.

Ch10. DB연동과 정규식

“DB 와 파이썬을 어떻게 연동할 수 있는지”

이 챕터 역시 데이터 베이스를 아직 배우기 전이기 때문에 큰 부담없이 파이썬에서 이렇게 db 를 연동시킬 수 있구나 정도를 이해하면 된다고 하였다.

KakaoTalk_Photo_2021-12-09-10-59-53

KakaoTalk_Photo_2021-12-09-11-00-05

정규식 관련 부분은 예전에 웹 스크래핑 할 때 re 로 한참 이것저것 했었던 것 같은데 역시 안 하면 까먹는 것 같다. 그래서 필요할 때 구글링해보면 될 것 같아서 따로 정리하지는 않았다.

Ch12. Rest API 와 Flask (와 파이썬)

해당 챕터는 강사님이 실제 파이썬을 도대체 어떻게 활용할 수 있죠? 라는 질문에 맛보기로 답하기 위해서 넣은 추가 챕터라고 한다. 따라서 짧은 강의를 듣는다고 모든 내용을 알 수도 없고 그런 취지로 올리신 것도 아닌 것 같아서 간단하게 파이썬으로 이런 것도 할 수 있구나 정도를 이해하고 넘어갔다. Flask 는 Django 와 비슷한 파이썬으로 할 수 있는 백엔드 정도로 이해하였고 이 밖에 API , Rest API 개념 역시 ‘비전공자를 위한 이해할 수 있는 IT 지식’ 책으로 복습하였다.

API (Application Programming Interface) :

API를 본격적으로 알아보기 전에, 비유를 들어 쉽게 설명을 도와드리겠습니다. 여러분이 멋진 레스토랑에 있다고 가정해봅시다. 점원이 가져다준 메뉴판을 보면서 먹음직스러운 스테이크를 고르면, 점원이 주문을 받아 요리사에 요청을 할 텐데요. 그러면 요리사는 정성껏 스테이크를 만들어 점원에게 주고, 여러분은 점원이 가져다준 맛있는 음식을 먹을 수 있게 됩니다.

여기서 점원의 역할을 한 번 살펴보겠습니다. 점원은 손님에게 메뉴를 알려주고, 주방에 주문받은 요리를 요청합니다. 그다음 주방에서 완성된 요리를 손님께 다시 전달하지요. API는 점원과 같은 역할을 합니다. API는 손님(프로그램)이 주문할 수 있게 메뉴(명령 목록)를 정리하고, 주문(명령)을 받으면 요리사(응용프로그램)와 상호작용하여 요청된 메뉴(명령에 대한 값)를 전달합니다. 쉽게 말해, API는 프로그램들이 서로 상호작용하는 것을 도와주는 매개체로 볼 수 있습니다.

출처 : API란? 비개발자가 알기 쉽게 설명해드립니다!

한마디로 API 는 클라이언트, 서버 등 서로 다른 프로그램에서 요청과 응답을 주고 받을 수 있게 만든 체계이다.

Rest API : 좀 더 체계적으로 API 를 관리하기 위한, 더 발전된 API

Restful API 는 메인 4개 요청 (C,R,U,D) 을 하나의 주소로 관리하고, 요청을 보낼 때 어떤 요청을 보냈는지 파악할 수 있는 스티커를 붙여서 함께 전송한다.

  • Create (“생성해줘”) : POST
  • Read (“불러와 줘”) : GET
  • Update (“바꿔줘”) : PUT(전체) / PATCH(일부)
  • Delete(“지워줘”) : DELETE

Ch13. 파이썬 속도 문제

이 부분도 추가 강의여서 파이썬은 고수준 언어에 가까워서 속도는 상대적으로 느린 편이고 그래서 이를 보완하기 위해 c 기반 pypy3 compiler 나 cython 을 사용할 수 있다 정도로만 들었다. (pypy3 는 코테 사이트에서 가끔 사용할 때가 있어서 조금 익숙하긴 했지만 사용해본 적은 없다. 나중에 진짜 사용할 필요가 생겼을 때 제대로 공부해보고 정리한 내용을 올려야겠다. )