본문 바로가기

implement_ml_models/CNN

implement_cnn (수정1)

코드 부분의 오류가 있어 수정,

cnn 클래스의 same_padding_cnn 부분

기존 코딩 부분

  # 패딩 cnn 연산 수행
  def same_padding_cnn(self, input, filter_size, filter_count):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []
    
    # 데이터 크기 지정
    self.data_size = input.shape[0]

    # 가중치 행렬 생성
    weight_arr = []

    # 입력 받은 필터의 개수만큼 반복
    for i in range(filter_count):

      # 필터 크기에 맞는 임의의 가중치 생성
      weight = np.random.random(filter_size * filter_size).reshape(filter_size, filter_size)
      
      weight_arr.append(weight)
      
      # 합성곱 연산 결과가 저장된다.
      result_arr = []

      # 합성곱 연산 수행
      for col in range(input.shape[0] - weight.shape[0] + 1):
        for row in range(input.shape[1] - weight.shape[1] + 1):
          result = []
          for w_col in range(weight.shape[0]):
            for w_row in range(weight.shape[1]):
              result.append(input[col + w_col, row + w_row ] * weight[w_col, w_row])
          result_arr.append(np.sum(result))

      # 연산 결과를 크기에 맞게 바꿔준다.
      result_arr = np.array(result_arr).reshape(input.shape[0] - weight.shape[0] + 1, -1)

      result_arr = self.pad.padding(result_arr, input.shape[0] - result_arr.shape[0])

      # 연산 결과의 저장
      filter_result_arr.append(result_arr)

    # 가중치의 저장
    self.cnn_weight.append(weight_arr)   
    
    # 층에다가 결과를 저장한다.
    self.layer_result.append(filter_result_arr)

    # 레이어의 추가
    self.layer = self.layer +1

패딩 연산을 합성곱 연산 후 잘못 시행,

입력값의 패딩 후 cnn 연산을 수행해야 한다.

1 : 먼저 각 필터별 합성곱 결과 행렬을 저장할 공간이 필요,

2 : 입력 데이터의 크기 측정(정사각 모양의 이미지라고 가정)

3 : 가중치 값을 저장하기 위한 배열 선언

4 : 필터 개수만큼의 반복,

5 : 입력된 크기에 맞는 임의의 가중치 생성

6 : cnn 연산 후 동일한 크기의 출력을 얻기 위해 padding 의 수행,

7 : padding 을 수행한 데이터에 대해 합성곱 연산 수행,

8 : padding 수행 시 원본 데이터에 대해 수행, 

 

바뀐 부분에 대한 코딩

  # 패딩 cnn 연산 수행
  def same_padding_cnn(self, input, filter_size, filter_count):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []
    
    # 데이터 크기 지정
    data_size = input.shape[0]

    # 가중치 행렬 생성
    weight_arr = []

    # 입력 받은 필터의 개수만큼 반복
    for i in range(filter_count):

      # 커널 크기에 맞는 임의의 가중치 생성
      weight = np.random.random(filter_size * filter_size).reshape(filter_size, filter_size)
      
      # 가중치의 저장
      weight_arr.append(weight)
      
      # 합성곱 연산 결과가 저장된다.
      result_arr = []

      # 합성곱을 시행할 패딩을 수행한 입력값
      padding_matrix = self.pad.padding(input, int(data_size / 2))

      # 합성곱 연산 수행
      for col in range(input.shape[0]):
        for row in range(input.shape[1]):
          result = []
          for w_col in range(weight.shape[0]):
            for w_row in range(weight.shape[1]):
              result.append(padding_matrix[col + w_col, row + w_row ] * weight[w_col, w_row])
          result_arr.append(np.sum(result))

      # 연산 결과를 크기에 맞게 바꿔준다.
      result_arr = np.array(result_arr).reshape(data_size, -1)

      # 연산 결과의 저장
      filter_result_arr.append(result_arr)

    # 가중치의 저장
    self.cnn_weight.append(weight_arr)   
    
    # 층에다가 결과를 저장한다.
    self.layer_result.append(filter_result_arr)

    # 레이어의 추가
    self.layer = self.layer +1

 

이전 출력에 대해 합성곱 연산을 수행하는 layer_cnn 함수

수정 전

  # 두 번째 층 이후의 cnn 연산 함수, 입력값은 이전 층의 출력이 된다.
  def layer_cnn(self, filter_size, filter_count):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []

    # 각 layer 별 가중치를 저장할 리스트
    weight_arr = []

    # 입력 받은 필터의 개수만큼 반복
    for i in range(filter_count):

      # 필터 크기에 맞는 임의의 가중치 생성
      weight = np.random.random(filter_size * filter_size).reshape(filter_size, filter_size)
      
      weight_arr.append(weight)
      
      # 합성곱 연산 결과가 저장된다.
      result_arr = []

      # 합성곱 연산 수행. 이전 레이어의 필터 출력 크기에 맞게 반복이 시행된다.
      for col in range(self.layer_result[self.layer - 1][0].shape[0] - weight.shape[0] + 1):
        for row in range(self.layer_result[self.layer - 1][0].shape[1] - weight.shape[1] + 1):
          result = []
          for w_col in range(weight.shape[0]):
            for w_row in range(weight.shape[1]):
              result.append(input[col + w_col, row + w_row ] * weight[w_col, w_row])
          result_arr.append(np.sum(result))
          
      # 연산 결과를 크기에 맞게 바꿔준다.
      result_arr = np.array(result_arr).reshape(self.layer_result[self.layer - 1][0].shape[0] - weight.shape[0] + 1, -1)

      result_arr = self.pad.padding(result_arr, self.layer_result[self.layer - 1][0].shape[0] - result_arr.shape[0])

      # 연산 결과의 저장
      filter_result_arr.append(result_arr)
    
    # 층에다가 결과를 저장한다.
    self.layer_result.append(filter_result_arr)

    # 가중치의 저장
    self.cnn_weight.append(weight_arr)

    # 레이어의 추가
    self.layer = self.layer +1

마찬가지로 패딩에 대한 오류 수정 및 데이터 호출 방식의 변경 

  # 두 번째 층 이후의 cnn 연산 함수, 입력값은 이전 층의 출력이 된다.
  def layer_cnn(self, filter_size, filter_count):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []

    # 각 layer 별 가중치를 저장할 리스트
    weight_arr = []

    # 입력 받은 필터의 개수만큼 반복
    for i in range(filter_count):

      # 필터 크기에 맞는 임의의 가중치 생성
      weight = np.random.random(filter_size * filter_size).reshape(filter_size, filter_size)
      
      weight_arr.append(weight)
      
      # 합성곱 연산 결과가 저장된다.
      result_arr = []

      # 합성곱을 시행할 패딩을 수행한 입력값
      padding_matrix = self.pad.padding(self.layer_result[-1], int(self.layer_result[-1].shape[0] / 2))

      # 합성곱 연산 수행. 이전 레이어의 필터 출력 크기에 맞게 반복이 시행된다.
      for col in range(self.layer_result[-1].shape[0]):
        for row in range(self.layer_result[-1].shape[1]):
          result = []
          for w_col in range(weight.shape[0]):
            for w_row in range(weight.shape[1]):
              result.append(padding_matrix[col + w_col, row + w_row ] * weight[w_col, w_row])
          result_arr.append(np.sum(result))
          
      # 연산 결과를 크기에 맞게 바꿔준다.
      result_arr = np.array(result_arr).reshape(self.layer_result[-1].shape[0], -1)

      # 연산 결과의 저장
      filter_result_arr.append(result_arr)
    
    # 가중치의 저장
    self.cnn_weight.append(weight_arr)

    # 층에다가 결과를 저장한다.
    self.layer_result.append(filter_result_arr)

    # 레이어의 추가
    self.layer = self.layer +1

 

pooling 함수의 수정, 수정 전 코드

  def pooling(self, pooling_size):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []

    # 이전 레이어의 필터 개수만큼 반복.
    for i in range(len(self.layer_result[self.layer - 1])):
      # numpy array 의 반환
      pooling_result = self.pool.max_pooling(self.layer_result[self.layer - 1][i], pooling_size)

      filter_result_arr.append(pooling_result)
    
    self.layer_result.append(filter_result_arr)

    # 레이어의 추가
    self.layer = self.layer +1

호출 방식의 변경

  def pooling(self, pooling_size):
    # 각 필터별 연산 결과를 저장할 리스트
    filter_result_arr = []

    # 이전 레이어의 필터 개수만큼 반복.
    for i in range(len(self.layer_result[-1])):
      # numpy array 의 반환
      pooling_result = self.pool.max_pooling(self.layer_result[-1][i], pooling_size)

      filter_result_arr.append(pooling_result)
    
    self.layer_result.append(filter_result_arr)

    # 레이어의 추가
    self.layer = self.layer +1

 

POOLING 클래스의 max_pooling 의 수정

수정 전

  def max_pooling(self, input, pooling_size):
    """
    input : 입력 데이터
    pooling_size : pooling size
    """
    self.pool_result = []
    
    pooling_matrix = self.pad.padding(input, input.shape[0] % pooling_size)

    for col in range(0, pooling_matrix.shape[0], pooling_size):
      for row in range(0, pooling_matrix.shape[1], pooling_size):
        pool_arr = []
        for pooling_col in range(pooling_size):
          for pooling_row in range(pooling_size):        
            pool_arr.append(pooling_matrix[pooling_col + col, pooling_row + row])
        self.pool_result.append(max(pool_arr))
    
    # 연산 결과를 크기에 맞게 바꿔준다.
    return np.array(self.pool_result).reshape(int(pooling_matrix.shape[0] / pooling_size), -1)

풀링 전 패딩 수행 시, 패딩 사이즈에 대한 오류 존재, 

(4,4) 입력에 대해 3사이즈의 풀링 수행 시 6의 크기를 입력해줘야 하므로 padding_size 에 2 가 입력되어야 한다.

  def max_pooling(self, input, pooling_size):
    """
    input : 입력 데이터
    pooling_size : pooling size
    """
    self.pool_result = []
    
    pooling_matrix = self.pad.padding(input, input.shape[0] - (input.shape[0] % pooling_size))

    for col in range(0, pooling_matrix.shape[0], pooling_size):
      for row in range(0, pooling_matrix.shape[1], pooling_size):
        pool_arr = []
        for pooling_col in range(pooling_size):
          for pooling_row in range(pooling_size):        
            pool_arr.append(pooling_matrix[pooling_col + col, pooling_row + row])
        self.pool_result.append(max(pool_arr))
    
    # 연산 결과를 크기에 맞게 바꿔준다.
    return np.array(self.pool_result).reshape(int(pooling_matrix.shape[0] / pooling_size), -1)

padding_size 의 입력값 수식 변경

'implement_ml_models > CNN' 카테고리의 다른 글

implement_cnn (수정3)  (0) 2023.03.18
implement_cnn (수정2)  (1) 2023.03.18
implement_CNN(CNN_backpropagation_cnn)  (0) 2023.03.16
implement_CNN(CNN_backpropagation_pooing)  (0) 2023.03.15
implement_CNN(CNN_backpropagation)  (0) 2023.03.14