페이지

2022년 8월 14일 일요일

11.1 Function 클래스 수정

 가변 길이 입출력을 표현하려면 변수들을 리스트(또는 튜플)에 넣어 처리하면 편할 것 같습니다. 즉, Function 클래스는 지금까지처럼 '하나의 인수'만 받고 '하나의 값'만 반환하는 것이죠. 대신 인수와 반환값의 타입을 리스트로 바꾸고, 필요한 변수들을 이 리스트에 넣으면 됩니다.

파이썬의 리스트와 튜플은 여러 개의 데이터를 한 줄로 저장합니다. 리스트는 [1, 2, 3]과 같이 []로 묶고 튜플은 (1, 2, 3)과 같이 ()로 묶습니다. 리스트와 튜플의 주요 차이는 원소를 변경할 수 있는지 여부입니다. 튜플의 경우 한번 생성되면 원소를 변경할 수 없습니다. 옐르 들어  x = (1, 2, 3)으로 튜플을 생성한 후 에는 x[0]  = 4 등으로 덮어 쓸 수 없는 것이죠. 반면 리스트는 원소를 변경할 수 있습니다.


그러면 현재의 Function 클래스가 어떻게 구현되어 있는지부터 확인해 보죠.

class Function:
  def __call__(selfinput):
    x = input.data  #1
    y = self.forward(x) #2
    output = Variable(as_array(y))  #3
    output.set_creator(self)  #4
    self.input = input
    self.output = output
    return output
  
  def forward(selfx):
    raise NotImplementedError()
  
  def backward(selfgy):
    raise NotImplementedError()


Function의 __call__메서드는 Variable이라는 '상자'에서 실제 데이터를 꺼낸 다음 forward메서드에서 구체적인 계산을 합니다. 그리고 계산 결과를 Variable에 넣고 자신이 '창조자'라고 원산지를 표시합니다. 이상의 로직을 염두에 두고 __call__메서드의 인수와 반환값을 리스트로 바꿔보겠습니다.

 

class Function:
  def __call__(selfinputs):
    xs = [x.data for x in inputs]
    ys = self.forward(xs)
    outputs = [Variable(as_array(y)) for y in ys ]

    for output in outputs:
      output.set_creator(self)
    self.inputs = inputs
    self.outputs = outputs
    return outputs
  
  def forward(selfxs):
    raise NotImplementedError()

  def backward(selfgys):
    raise NotImplementedError()

인수와 반환값을 리스트로 변경했습니다. 변수를 리스트에 담아 취급한다는 점을 제외하고는 달라진 게 없습니다. 참고로 앞의 코드에서는 리스트를 생성할 때 리스트 내포(list comprehension)를 사용했습니다.


리스트 내포는 xs = [x.data for x in inputs] 형태로 사용합니다. 이 코드는 inputs 리스트의 각 원소 x에 대해 각각의 데이터(x.data)를 꺼내고, 꺼낸 원소들로 구성된 새로운 리스트를 만듭니다.


이상이 새로운 Function 클래스입니다. 이어서 새로운 Function클래스를 사용하여 구체적인 함수를 구현하겠습니다. 첫 번째는 덧셈을 해주는 Add클래스 차례입니다.

댓글 없음: