鉴于用python写神经网络、卷积神经网络的话,不利于框架直接用numpy等来完成,速度实在是慢的吓人,所以改用c++来写。c++的话什么操作基本都要自己定义。由于卷积神经网络主要针对图像类,故最好定义一个适用于图像类的矩阵类,我这边使用了网上一个开源的用c++写好的卷积神经网络,使用了里面定义好的矩阵类,如下。这个类个人觉得非常好用,故写成博客,收藏一波,方便以后使用时候查找。

首先导入需要的模块:

#include <math.h>
#include <string.h>
#include <string>
#include <cstdlib>
#include <random>
#include <algorithm>

然后定义一个矩阵类,主要用于图像处理方面:
里面包括了矩阵的各种属性,宽、高、通道数,大小,元素个数等,以及对矩阵的各种操作,包括padding、翻转等,还有矩阵之间的各种运算,+、-、*、+=等。。。

namespace mojo
{enum pad_type { zero = 0, edge = 1, median_edge = 2 };// matrix class ---------------------------------------------------
// should use opencv if available
//class matrix
{int _size;int _capacity;float *_x_mem;void delete_x() { delete[] _x_mem; x = NULL;  _x_mem = NULL; }// 4 extra for alignment and 4 for 3 padding for SSE//float *new_x(const int size) { _x_mem = new float[size + 4+3];  x = (float *)(((uintptr_t)_x_mem + 16) & ~(uintptr_t)0x0F); return x; }// avx mem aligmentfloat *new_x(const int size) { _x_mem = new float[size + 8 + 7];  x = (float *)(((uintptr_t)_x_mem + 32) & ~(uintptr_t)0x1F); return x; }
public:std::string _name;int cols, rows, chans;int chan_stride;int chan_aligned;float *x;// size must be divisible by 8 for AVXvirtual int calc_chan_stride(int w, int h){if (chan_aligned){int s = w*h;const int remainder = s % 8;if (remainder > 0) s += 8 - remainder;return s;}else return w*h;}matrix( ): cols(0), rows(0), chans(0), _size(0), _capacity(0), chan_stride(0), x(NULL), chan_aligned(0)/*, empty_chan(NULL)*/{}matrix( int _w, int _h, int _c=1, const float *data=NULL, int align_chan=0): cols(_w), rows(_h), chans(_c){chan_aligned = align_chan;chan_stride = calc_chan_stride(cols, rows);_size= chan_stride*chans; _capacity=_size; x = new_x(_size);if(data!=NULL) memcpy(x,data,_size*sizeof(float));}// copy constructor - deep copymatrix( const matrix &m) : cols(m.cols), rows(m.rows), chan_aligned(m.chan_aligned), chans(m.chans), chan_stride(m.chan_stride), _size(m._size), _capacity(m._size)   {x = new_x(_size); memcpy(x,m.x,sizeof(float)*_size); /*empty_chan = new unsigned char[chans]; memcpy(empty_chan, m.empty_chan, chans);*/} // { v=m.v; x=(float*)v.data();}// copy and pad constructormatrix( const matrix &m, int pad_cols, int pad_rows, mojo::pad_type padding= mojo::zero, int threads=1) : cols(m.cols), rows(m.rows), chans(m.chans), chan_aligned(m.chan_aligned), chan_stride(m.chan_stride), _size(m._size), _capacity(m._size){x = new_x(_size); memcpy(x, m.x, sizeof(float)*_size);*this = pad(pad_cols, pad_rows, padding, threads);}~matrix() { if (x) delete_x(); }matrix get_chans(int start_channel, int num_chans=1) const{return matrix(cols,rows,num_chans,&x[start_channel*chan_stride]);}// if edge_pad==0, then the padded area is just 0. // if edge_pad==1 it fills with edge pixel colors// if edge_pad==2 it fills with median edge pixel colormatrix pad(int dx, int dy, mojo::pad_type edge_pad = mojo::zero, int threads=1) const{return pad(dx, dy, dx, dy, edge_pad, threads);}matrix pad(int dx, int dy, int dx_right, int dy_bottom, mojo::pad_type edge_pad = mojo::zero, int threads=1) const{matrix v(cols+dx+dx_right,rows+dy+dy_bottom,chans);//,NULL,this->chan_aligned);v.fill(0);//float *new_x = new float[chans*w*h];
#pragma omp parallel for num_threads(threads)for(int k=0; k<chans; k++){const int v_chan_offset=k*v.chan_stride;const int chan_offset=k*chan_stride;// find median color of perimeterfloat median = 0.f;if (edge_pad == mojo::median_edge){int perimeter = 2 * (cols + rows - 2);std::vector<float> d(perimeter);for (int i = 0; i < cols; i++){d[i] = x[i+ chan_offset]; d[i + cols] = x[i + cols*(rows - 1)+ chan_offset];}for (int i = 1; i < (rows - 1); i++){d[i + cols * 2] = x[cols*i+ chan_offset];// file from back so i dont need to cal indexd[perimeter - i] = x[cols - 1 + cols*i+ chan_offset];}std::nth_element(d.begin(), d.begin() + perimeter / 2, d.end());median = d[perimeter / 2];//for (int i = 0; i < v.rows*v.cols; i++) v.x[v_chan_offset + i] = solid_fill;}for(int j=0; j<rows; j++){memcpy(&v.x[dx+(j+dy)*v.cols+v_chan_offset], &x[j*cols+chan_offset], sizeof(float)*cols);if(edge_pad== mojo::edge){// do left/right sidefor(int i=0; i<dx; i++) v.x[i+(j+dy)*v.cols+v_chan_offset]=x[0+j*cols+chan_offset];for (int i = 0; i<dx_right; i++) v.x[i + dx + cols + (j + dy)*v.cols + v_chan_offset] = x[(cols - 1) + j*cols + chan_offset];}else if (edge_pad == mojo::median_edge){for (int i = 0; i < dx; i++) v.x[i + (j + dy)*v.cols + v_chan_offset] = median;for (int i = 0; i < dx_right; i++) v.x[i + dx + cols + (j + dy)*v.cols + v_chan_offset] = median;}}// top bottom padif(edge_pad== mojo::edge){for(int j=0; j<dy; j++)   memcpy(&v.x[(j)*v.cols+v_chan_offset],&v.x[(dy)*v.cols+v_chan_offset], sizeof(float)*v.cols);for (int j = 0; j<dy_bottom; j++) memcpy(&v.x[(j + dy + rows)*v.cols + v_chan_offset], &v.x[(rows - 1 + dy)*v.cols + v_chan_offset], sizeof(float)*v.cols);}if (edge_pad == mojo::median_edge){for (int j = 0; j<dy; j++) for (int i = 0; i<v.cols; i++) v.x[i + j*v.cols + v_chan_offset] = median;for (int j = 0; j<dy_bottom; j++) for (int i = 0; i<v.cols; i++) v.x[i + (j + dy + rows)*v.cols + v_chan_offset] = median;}}return v;}matrix crop(int dx, int dy, int w, int h, int threads=1) const{matrix v(w,h,chans);#pragma omp parallel for num_threads(threads)for(int k=0; k<chans; k++){for(int j=0; j<h; j++){memcpy(&v.x[j*w+k*v.chan_stride], &x[dx+(j+dy)*cols+k*chan_stride], sizeof(float)*w);}}return v;}mojo::matrix shift(int dx, int dy, mojo::pad_type edge_pad=mojo::zero){int orig_cols=cols;int orig_rows=rows;int off_x=abs(dx);int off_y=abs(dy);mojo::matrix shifted= pad(off_x, off_y, edge_pad);return shifted.crop(off_x-dx, off_y-dy,orig_cols,orig_rows);}mojo::matrix flip_cols(){mojo::matrix v(cols,rows,chans);for(int k=0; k<chans; k++)for(int j=0; j<rows; j++)for(int i=0; i<cols; i++)v.x[i+j*cols+k*chan_stride]=x[(cols-i-1)+j*cols+k*chan_stride];return v;}mojo::matrix flip_rows(){mojo::matrix v(cols, rows, chans);for (int k = 0; k<chans; k++)for (int j = 0; j<rows; j++)memcpy(&v.x[(rows-1-j)*cols + k*chan_stride],&x[j*cols + k*chan_stride], cols*sizeof(float));return v;}void clip(float min, float max){int s = chan_stride*chans;for (int i = 0; i < s; i++){if (x[i] < min) x[i] = min;if (x[i] > max) x[i]=max;}}void min_max(float *min, float *max, int *min_i=NULL, int *max_i=NULL){int s = rows*cols;int mini = 0;int maxi = 0; for (int c = 0; c < chans; c++){const int t = chan_stride*c;for (int i = t; i < t+s; i++){if (x[i] < x[mini]) mini = i;if (x[i] > x[maxi]) maxi = i;}}*min = x[mini];*max = x[maxi];if (min_i) *min_i = mini;if (max_i) *max_i = maxi;}float mean(){const int s = rows*cols;int cnt = 0;// channel*s;float average = 0;for (int c = 0; c < chans; c++){const int t = chan_stride*c;for (int i = 0; i < s; i++)average += x[i + t];}average = average / (float)(s*chans);return average;}float remove_mean(int channel){int s = rows*cols;int offset = channel*chan_stride;float average=0;for(int i=0; i<s; i++) average+=x[i+offset];      average= average/(float)s;for(int i=0; i<s; i++) x[i+offset]-=average;     return average;}float remove_mean(){float m=mean();int s = chan_stride*chans;//int offset = channel*s;for(int i=0; i<s; i++) x[i]-=m;     return m;}void fill(float val) { for(int i=0; i<_size; i++) x[i]=val; }void fill_random_uniform(float range){std::mt19937 gen(0);std::uniform_real_distribution<float> dst(-range, range);for (int i = 0; i<_size; i++) x[i] = dst(gen);}void fill_random_normal(float std){std::mt19937 gen(0);std::normal_distribution<float> dst(0, std);for (int i = 0; i<_size; i++) x[i] = dst(gen);}// deep copyinline matrix& operator =(const matrix &m){resize(m.cols, m.rows, m.chans, m.chan_aligned);memcpy(x,m.x,sizeof(float)*_size);
//      memcpy(empty_chan, m.empty_chan, chans);return *this;}int  size() const {return _size;} void resize(int _w, int _h, int _c, int align_chans=0) { chan_aligned = align_chans;int new_stride = calc_chan_stride(_w,_h);int s = new_stride*_c;if(s>_capacity) { if(_capacity>0) delete_x(); _size = s; _capacity=_size; x = new_x(_size);}cols = _w; rows = _h; chans = _c; _size = s; chan_stride = new_stride; } // dot vector to 2d matinline matrix dot_1dx2d(const matrix &m_2d) const{mojo::matrix v(m_2d.rows, 1, 1);for(int j=0; j<m_2d.rows; j++) v.x[j]=dot(x,&m_2d.x[j*m_2d.cols],_size);return v;}// +=inline matrix& operator+=(const matrix &m2){for(int i = 0; i < _size; i++) x[i] += m2.x[i];return *this;}// -=inline matrix& operator-=(const matrix &m2) {for (int i = 0; i < _size; i++) x[i] -= m2.x[i];return *this;}// *= floatinline matrix operator *=(const float v) {for (int i = 0; i < _size; i++) x[i] = x[i] * v;return *this;}inline matrix operator *=(const matrix &v) {for (int i = 0; i < _size; i++) x[i] = x[i] * v.x[i];return *this;}inline matrix operator *(const matrix &v) {matrix T(cols, rows, chans);for (int i = 0; i < _size; i++) T.x[i] = x[i] * v.x[i];return T;}// * floatinline matrix operator *(const float v) {matrix T(cols, rows, chans);for (int i = 0; i < _size; i++) T.x[i] = x[i] * v;return T;}// + floatinline matrix operator +(const float v) {matrix T(cols, rows, chans);for (int i = 0; i < _size; i++) T.x[i] = x[i] + v;return T;}// +inline matrix operator +(matrix m2){matrix T(cols,rows,chans);for(int i = 0; i < _size; i++) T.x[i] = x[i] + m2.x[i]; return T;}// -inline matrix operator -(matrix m2){matrix T(cols, rows, chans);for (int i = 0; i < _size; i++) T.x[i] = x[i] - m2.x[i];return T;}};}// namespace

使用C++编写卷积神经网络(一)相关推荐

  1. 零基础入门深度学习(4) - 卷积神经网络

    无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作为一个有理想有追求的程序员,不懂深度学习(Deep Learning)这个超热的技术,会不会感觉马上就o ...

  2. 深度学习(5) - 卷积神经网络

    一个新的激活函数--Relu 最近几年卷积神经网络中,激活函数往往不选择sigmoid或tanh函数,而是选择relu函数.Relu函数的定义是: Relu函数图像如下图所示: Relu函数作为激活函 ...

  3. [Python人工智能] 八.卷积神经网络CNN原理详解及TensorFlow编写CNN

    从本专栏开始,作者正式开始研究Python深度学习.神经网络及人工智能相关知识.前一篇文章介绍了什么是过拟合,并采用droput解决神经网络中过拟合的问题,以TensorFlow和sklearn的lo ...

  4. 基于Java机器学习自学笔记(第81-87天:CNN卷积神经网络的入门到全代码编写)

    注意:本篇为50天后的Java自学笔记扩充,内容不再是基础数据结构内容而是机器学习中的各种经典算法.这部分博客更侧重于笔记以方便自己的理解,自我知识的输出明显减少,若有错误欢迎指正! 目录 1. CN ...

  5. Python 卷积神经网络 ResNet的基本编写方法

    ResNet(Residual Network)是由微软亚洲研究院提出的深度卷积神经网络,它在2015年的ImageNet挑战赛上取得了第一名的好成绩.ResNet最大的特点是使用了残差学习,可以解决 ...

  6. 编写一个卷积神经网络识别汉服领型的代码

    我可以提供一个基于卷积神经网络的示例代码来识别汉服领型:import numpy as np import pandas as pd from keras.models import Sequenti ...

  7. 深入卷积神经网络背后的数学原理 | 技术头条

    参加「CTA 核心技术及应用峰会」,请扫码报名 ↑↑↑ 作者 | Piotr Skalski 译者 | Monanfei 编辑 | 十月Rachel.Jane 出品 | AI科技大本营(id:rgzn ...

  8. 卷积神经网络(CNN)实现CIFAR100类别分类

    卷积神经网络(CNN)实现CIFAR100类别分类 1. CIFAR100数据集介绍 这个数据集就像CIFAR-10,除了它有100个类,每个类包含600个图像.,每类各有500个训练图像和100个测 ...

  9. 刷脸背后,卷积神经网络的数学原理原来是这样的

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|深度学习这件小事 计算机视觉技术在日常生活中有着非常普遍 ...

  10. C++ 中的卷积神经网络 (CNN)

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 有很多卷积神经网络文章解释了 CNN 是什么以及它的用途是什么,而 ...

最新文章

  1. LeetCode 542. 01 Matrix--C++解法--动态规划
  2. C语言判断是否为happy number快乐数字的算法(附完整源码)
  3. AjaxControlToolkit的使用
  4. 华为云WeLink正式发布,这是更懂企业的智能工作平台一枚!
  5. faster-RCNN台标检测
  6. Java NIO之DatagramChannel
  7. SocksCap代理
  8. redhat官网关于生成rpm包的文章
  9. vs201中debug和release两个版本的区别
  10. 大数据给人们生活带来的改变_大数据给我们的生活带来了哪些改变?
  11. 安装 配置BlackBerry Push Service SDK v1.1.0
  12. 佛理(引用别人的东西,怕忘记了不好找,拿来了,哈哈)
  13. 数理统计之 置信区间2
  14. 大才非学不成,大志非学不就——周旭龙
  15. Windows下查看Android手机APP日志
  16. uniapp实现app跳转app
  17. win7 两台PC网线直连创建家庭组局域网分享文件
  18. 倍福PLC基于NT_Shutdown实现控制器自动关机重启
  19. Mac安装多版本java
  20. MeasureSpec源码解读

热门文章

  1. 华为员工年薪 200 万!真相让人心酸!
  2. 【狂神说Java】SpringBoot最新教程IDEA版通俗易懂
  3. Android WIFI的管理方法
  4. github注册关于QQ邮箱验证码问题
  5. TTL电平信号和RS232信号波形对比
  6. mysql frm myd myi 恢复_恢复 - 如何从.myd,.myi,.frm文件恢复MySQL数据库
  7. USB:Type-A、Type-B、Type-C、miniUSB、microUSB接口类型区分
  8. 需要管理员权限解决办法
  9. tomcat如何知道WebRoot是web根目录?
  10. 电脑插入U盘后里面的文件变成快捷方式解决办法