코드 부분의 오류가 있어 수정,
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 |