tiny_cn 소스 코드 읽 기 (4) - convolutionallayer

  • connection_table
  • index3d
  • convolutional_layer

  • 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++) {

    그 다음 에 바이어스 를 추가 하여 최종 결 과 를 계산한다.

    좋은 웹페이지 즐겨찾기