tiny_cn 소스 코드 읽 기 (4) - convolutionallayer
10074 단어 tiny_cn 소스 코드 읽 기
convolutional_layer 는 볼 륨 을 계산 하 는 데 쓰 인 다.
connection_table
connecction_table 은 2 차원 배열 입 니 다. (x, y) 의 값 (true / false) 은 x 와 y 가 연결 되 어 있 는 지 여 부 를 표시 합 니 다. 즉, 그 몇 개의 feature map 와 연결 되 어 있 는 지 판단 하 는 데 사 용 됩 니 다. 이 실현 에서 내부 데이터 구 조 는 bool 형식 대기 열 이 고 함수
is_connected
는 관련 여 부 를 판단 합 니 다.bool is_connected(cnn_size_t x, cnn_size_t y) const {// x,y 。 connection table ,
return is_empty() ? true : connected_[y * cols_ + x];
}
index3d
이 데이터 구 조 는 이미지 크기, 즉 너비 - 높이 - 깊이 만 기록 할 뿐 실제 데 이 터 를 가지 고 있 지 않 습 니 다.
template T>
struct index3d {// , , - - ,
index3d(T width, T height, T depth) {
reshape(width, height, depth);
}
index3d() : width_(0), height_(0), depth_(0) {}
void reshape(T width, T height, T depth) {
width_ = width;
height_ = height;
depth_ = depth;
if ((long long) width * height * depth > std::numeric_limits<T>::max())
throw nn_error(
format_str("error while constructing layer: layer size too large for tiny-cnn
WidthxHeightxChannels=%dx%dx%d >= max size of [%s](=%d)",
width, height, depth, typeid(T).name(), std::numeric_limits<T>::max()));
}
T get_index(T x, T y, T channel) const {
assert(x >= 0 && x < width_);
assert(y >= 0 && y < height_);
assert(channel >= 0 && channel < depth_);
return (height_ * channel + y) * width_ + x;
}
T area() const {
return width_ * height_;
}
T size() const {
return width_ * height_ * depth_;
}
T width_;
T height_;
T depth_;
};
convolutional_layer
convolutional layer 는 볼 륨 을 계산 하 는 데 사 용 됩 니 다. 먼저 구성원 변 수 를 보십시오.
const vec_t* prev_out_padded_[CNN_TASK_SIZE];// ,pad_type_ == padding::same ,
vec_t* prev_out_buf_[CNN_TASK_SIZE];
vec_t prev_delta_padded_[CNN_TASK_SIZE];// prev_delta_
vec_t prev_delta2_padded_;// prev_delta2_
connection_table tbl_;//connection_table
index3d in_;//
index3d in_padded_;// ,
index3d out_;//
index3d weight_;//
padding pad_type_;// , : - +1
size_t w_stride_;//stride 。 1, pooling
size_t h_stride_;
pad_type_
충전 유형 을 표시 합 니 다. 볼 륨 을 채 우지 않 으 면 볼 륨 핵 이 미 끄 러 질 때마다 거리 w_stride_
와 h_stride_
가 1 이면 볼 륨 후 이미지: 높이 = 원 높이 - 볼 륨 핵 높이 + 1, 너비 = 원 너비 - 볼 륨 핵 너비 + 1.볼 륨 층 의 중점 은 볼 륨 입 니 다. 볼 륨 함수 좀 보 세 요.
virtual const vec_t& forward_propagation(const vec_t& in_raw, size_t worker_index) override
{
copy_and_pad_input(in_raw, static_cast<int>(worker_index));
vec_t &a = a_[worker_index]; // w*x,
vec_t &out = output_[worker_index]; // output
const vec_t &in = *(prev_out_padded_[worker_index]); // input
std::fill(a.begin(), a.end(), float_t(0));
for_i(parallelize_, out_.depth_, [&](int o) {
for (cnn_size_t inc = 0; inc < in_.depth_; inc++) {
if (!tbl_.is_connected(o, inc)) continue;// connection_table ,connection_table
const float_t *pw = &this->W_[weight_.get_index(0, 0, in_.depth_ * o + inc)];//
const float_t *pi = &in[in_padded_.get_index(0, 0, inc)];//
float_t *pa = &a[out_.get_index(0, 0, o)];//pa
//
for (cnn_size_t y = 0; y < out_.height_; y++) {
for (cnn_size_t x = 0; x < out_.width_; x++) {
const float_t * ppw = pw;// , ppi
const float_t * ppi = pi + (y * h_stride_) * in_padded_.width_ + x * w_stride_;
float_t sum = float_t(0);
//
// should be optimized for small kernel(3x3,5x5)
for (cnn_size_t wy = 0; wy < weight_.height_; wy++) {
for (cnn_size_t wx = 0; wx < weight_.width_; wx++) {
sum += *ppw++ * ppi[wy * in_padded_.width_ + wx];// :sum( x )
}
}
pa[y * out_.width_ + x] += sum;//
}
}
}
//bias bias
if (!this->b_.empty()) {
float_t *pa = &a[out_.get_index(0, 0, o)];
float_t b = this->b_[o];
std::for_each(pa, pa + out_.width_ * out_.height_, [&](float_t& f) { f += b; });
}
});
for_i(parallelize_, out_size_, [&](int i) {
out[i] = h_.f(a, i);
});
CNN_LOG_VECTOR(in_raw, "[pc]in");
CNN_LOG_VECTOR(W_, "[pc]w");
CNN_LOG_VECTOR(a, "[pc]a");
CNN_LOG_VECTOR(out, "[pc]forward");
return next_ ? next_->forward_propagation(out, worker_index) : out;// ,
}
위의 변수
a_
는 다음 과 같이 저장 합 니 다: wx + b; out 는 f (wx + b) 를 저장 합 니 다. 가중치 저장 W_
에 서 는 함수 인자 in_raw
를 입력 하 십시오. 볼 륨 을 쌓 을 때 출력 된 픽 셀 마다://
for (cnn_size_t y = 0; y < out_.height_; y++) {
for (cnn_size_t x = 0; x < out_.width_; x++) {
그 다음 에 볼 륨 핵 을 옮 겨 다 니 며 특정한 구역 을 볼 륨 하여 wx 를 계산 합 니 다.
for (cnn_size_t wy = 0; wy < weight_.height_; wy++) {
for (cnn_size_t wx = 0; wx < weight_.width_; wx++) {
그 다음 에 바이어스 를 추가 하여 최종 결 과 를 계산한다.