dev_AI_framework
soft max backend 구현,
명징직조지훈
2024. 9. 9. 09:44
배치 데이터 입력
// Softmax 연산을 배치 데이터로 수행하도록 개별 노드로 분리하여 구현
std::pair<py::array_t<double>, std::vector<std::shared_ptr<Node>>> softmax(py::array_t<double> inputs) {
py::buffer_info buf = inputs.request();
if (buf.ndim != 2)
throw std::runtime_error("Input should be a 2-D array");
size_t num_rows = buf.shape[0];
size_t num_cols = buf.shape[1];
double* ptr = static_cast<double*>(buf.ptr);
py::array_t<double> result({num_rows, num_cols});
py::buffer_info buf_result = result.request();
double* ptr_result = static_cast<double*>(buf_result.ptr);
std::vector<std::shared_ptr<Node>> node_list;
// 각 행에 대해 Softmax 연산 수행
for (size_t row = 0; row < num_rows; ++row) {
double* row_ptr = ptr + row * num_cols;
double* row_result_ptr = ptr_result + row * num_cols;
// 각 행 별 최댓값
double max_val = *std::max_element(row_ptr, row_ptr + num_cols);
double sum = 0.0;
std::vector<std::shared_ptr<Node>> exp_nodes;
for (size_t i = 0; i < num_cols; ++i) {
double input_value = row_ptr[i];
// Subtract 노드 생성 (각 입력에서 최대값을 뺌)
double sub_output = input_value - max_val;
std::shared_ptr<Node> sub_node = std::make_shared<Node>("subtract", input_value, max_val, sub_output);
// Exponentiate 노드 생성 (exp(x))
double exp_output = std::exp(sub_output);
std::shared_ptr<Node> exp_node = std::make_shared<Node>("exp", sub_output, exp_output);
exp_node->add_child(sub_node);
sub_node->add_parent(exp_node);
exp_nodes.push_back(exp_node);
sum += exp_output;
}
for (size_t i = 0; i < num_cols; ++i) {
// Divide 노드 생성 (exp(x) / sum)
double div_output = exp_nodes[i]->output / sum;
std::shared_ptr<Node> div_node = std::make_shared<Node>("divide", exp_nodes[i]->output, sum, div_output);
div_node->add_child(exp_nodes[i]);
exp_nodes[i]->add_parent(div_node);
// 결과의 개수는 입력 데이터의 개수와 동일, 배치까지
node_list.push_back(div_node);
// 결과 저장
row_result_ptr[i] = div_output;
}
}
return std::make_pair(result, node_list);
}
각 행, 각 데이터에 대해 softmax 연산을 수행과 노드 저장
from dev.backend.activations import activations
import numpy as np
# 예시 입력
inputs = np.array([[-1.0, 0.5, 2.0], [1.0, -0.5, 0.0]])
# ReLU 연산
result, nodes = activations.relu(inputs)
print("ReLU Result:", result)
# Sigmoid 연산
result, nodes = activations.sigmoid(inputs)
print("Sigmoid Result:", result)
# Tanh 연산
result, nodes = activations.tanh(inputs)
print("Tanh Result:", result)
# Leaky ReLU 연산
result, nodes = activations.leaky_relu(inputs, alpha=0.01)
print("Leaky ReLU Result:", result)
# Softmax 연산
result, nodes = activations.softmax(inputs)
print("Softmax Result:", result)
"""
ReLU Result: [0. 0.5 2. 1. 0. 0. ]
Sigmoid Result: [0.26894142 0.62245933 0.88079708 0.73105858 0.37754067 0.5 ]
Tanh Result: [-0.76159416 0.46211716 0.96402758 0.76159416 -0.46211716 0. ]
Leaky ReLU Result: [-0.01 0.5 2. 1. -0.005 0. ]
Softmax Result: [[0.03911257 0.17529039 0.78559703] [0.62853172 0.14024438 0.2312239 ]]
"""
배치단위 입력이 일차원 리스트로 출력됨 크기 조정이 필요하네