C++元编程——Adam优化BP神经网络

bp神经网络学习很慢,所以用adam进行优化,测试代码如下,该代码用来求解二次方程,,当然可以训练出一个输入x^2+2*x得出x的神经网络:

#include <conio.h>
#include "bp.hpp"                                            // 神经网络头文件

int main(int argc, char** argv) 
{
	double d_pre_max = 0.0;
	double d_max = -1 * DBL_MAX;
	using net_type = net<1, 200, 1>;                        // 定义神经网络类型
	net_type n;                                             // 创建神经网络
	net_type::ret_type& mt_delta = n.get_delta();			// 引用,这样就永远不需要复制了
    int i_max_repeat_count= 0;
	for (double i = 0; ; i+=1) 
	{
		for (double j = 0.1; j < 0.6; j+=.01) 
		{
				double d_out = j;
				net_type::ret_type mt_expected({ d_out });		// 期望返回值
				net_type::input_type mt_input = { j * j + 2. * j };
				auto mt_out = n.forward(mt_input);
				n.backward(mt_expected);
				d_max = d_max < mt_delta.max_abs() ? mt_delta.max_abs() : d_max;
		}
		std::cout << d_max << std::endl;
		i_loop_num++;
		if (d_max < 1e-3/* || abs(d_pre_max - d_max) < 1e-11 */)
		{
			i_max_repeat_count++;
			std::cout << "-------" << d_max << "---------" << std::endl;
			if (i_max_repeat_count> 10)
			break;
		}
		else 
		{
			i_max_repeat_count--;
			if (i_max_repeat_count < 0)ooooo = 0;
		}
		d_pre_max = d_max;
		d_max = -1 * DBL_MAX;
	}
	for (double j = 0.1; j < 0.6; j += .1)
	{
		net_type::input_type mt_input = { j * j , 2 * j };
		auto mt_out = n.forward(mt_input);
		mt_out.print();
	}
	std::cout << "loop num:" << i_loop_num << std::endl;
	_getch();
	return 0;
}

以上的函数运行还行,就是并没有想像的那么快,模拟出上面那个函数都需要很长的时间。基础函数:

#ifndef _BASE_FUNCTION_HPP_
#define _BASE_FUNCTION_HPP_

template<typename func_t>
auto derivative(func_t&& f, const decltype(f(0))& v)
{
	constexpr double SMALL_VAL = 1e-11;
	return (f(v + SMALL_VAL) - f(v - SMALL_VAL)) / (2.*SMALL_VAL);
}

template<typename val_t = double>
val_t f_sigmoid(const val_t& v)
{
	return 1. / (1. + exp(-1. * v));
}

template<int r, int c>
class n_sigmoid
{
public:
	template<typename imatt, typename vt = double>
	static vt cal(const imatt& mt)
	{
		return f_sigmoid(mt.get(r, c));
	}
};

template<int r, int c>
class n_desigmoid
{
public:
	template<typename imatt, typename vt = double>
	static vt cal(const imatt& mt)
	{
		return derivative(f_sigmoid<vt>, mt.get(r, c));
	}
};

template<typename func_t>
struct der_func
{
	static constexpr double SMALL_VAL = 1e-7;
	static typename func_t::ret_type cal(const typename func_t::input_type& v)
	{
		return (func_t::cal(v + SMALL_VAL) - func_t::cal(v - SMALL_VAL)) / (2.*SMALL_VAL);
	}
};

struct func_sigmoid 
{
	using ret_type = double;
	using input_type = double;
	template<typename vt = double>
	static vt cal(const vt& v)
	{
		return f_sigmoid(v);
	}
};
#include "base_logic.hpp"

template<typename func_t>
class func_pack
{
public:
	template<int r, int c>
	struct normal_t
	{
		template<typename imatt, typename vt = double>
		static vt cal(const imatt& mt) 
		{
			return func_t::cal(mt.get(r,c));
		}
	};

	template<int r, int c>
	struct derivative_t 
	{
		template<typename imatt, typename vt = double>
		static vt cal(const imatt& mt)
		{
			return der_func<func_t>::cal(mt.get(r, c));
		}
	};

	template<int row_num, int col_num, typename val_t = double>
	mat<row_num, col_num, val_t> normal(const mat<row_num, col_num, val_t>& mt)
	{
		using omatt = mat<row_num, col_num, val_t>;
		omatt mt_ret;
		col_loop<col_num - 1, normal_t>(mt_ret, mt);
		return mt_ret;
	}

	template<int row_num, int col_num, typename val_t = double>
	mat<row_num, col_num, val_t> derivative(const mat<row_num, col_num, val_t>& mt)
	{
		using omatt = mat<row_num, col_num, val_t>;
		omatt mt_ret;
		col_loop<col_num - 1, derivative_t>(mt_ret, mt);
		return mt_ret;
	}
};

/* 点乘运算 */
template<int r1, int c1, int r2, int c2, typename imatt1, typename imatt2, typename vt = double>
inline vt n_dot(const imatt1& mt1, const imatt2& mt2)
{
	static_assert(c1 =&
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾昵猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值