C++ 如何初始化依赖于以前条目的可变模板?
我正在尝试实现一个神经网络。为此,我想我可以对大多数超参数使用模板参数。开始变得困难了,我怀疑这可能不可能实现我想要的 我有一个基本的神经元类C++ 如何初始化依赖于以前条目的可变模板?,c++,variadic-templates,C++,Variadic Templates,我正在尝试实现一个神经网络。为此,我想我可以对大多数超参数使用模板参数。开始变得困难了,我怀疑这可能不可能实现我想要的 我有一个基本的神经元类 class NeuronBase { /* virtual output method */ }; 由此我有了一个输入神经元 class InputNeuron : public NeuronBase { /* overrides output */ }; 以及大多数层中使用的适当神经元类型 template<std::size_t NumIn
class NeuronBase { /* virtual output method */ };
由此我有了一个输入神经元
class InputNeuron : public NeuronBase { /* overrides output */ };
以及大多数层中使用的适当神经元类型
template<std::size_t NumInputs>
class Neuron : public NeuronBase
{
public:
Neuron(std::array<NeuronBase*,NumInputs> prevLayer)
:
m_inputLayer(prevLayer)
{}
/* override output method */
protected:
std::array<NeuronBase*,NumInputs> m_inputLayer;
};
模板
类神经元:公共神经元库
{
公众:
神经元(标准::数组层)
:
m_输入层(前置层)
{}
/*重写输出方法*/
受保护的:
std::阵列m_输入层;
};
它们包含在一个层中:
template<std::size_t NumNeurons>
class Layer
{
public:
typedef std::array<NeuronBase*,NumNeurons> NeuronArray;
Layer(NeuronArray neurons)
:
m_neurons(neurons)
{}
NeuronArray& GetNeurons() const { return m_neurons; }
protected:
NeuronArray m_neurons;
};
模板
类层
{
公众:
typedef std::数组和数组;
层(神经元阵列)
:
m_神经元(神经元)
{}
NeuronArray&GetNeurons()常量{返回m_neurons;}
受保护的:
神经元阵列;
};
这些层由网络封装:
template<std::size_t NumInputs, std::size_t NumOutputs, std::size_t... HiddenSizes>
class NeuralNetwork
{
public:
NeuralNetwork()
:
m_hiddenLayers(/* WTF do I do?? */)
{
}
protected:
std::array<InputNeuron,NumInputs> m_inputLayer;
Layer<NumOutputs> m_outputLayer;
std::tuple<Layer<HiddenSizes>...> m_hiddenLayers;
};
模板
类神经网络
{
公众:
神经网络
:
m_隐藏层(/*我该怎么办?*/)
{
}
受保护的:
std::阵列m_输入层;
层m_输出层;
std::元组m_隐藏层;
};
将创建如下内容:
int main()
{
NeuralNetwork<126,7,252,63> nn;
return 0;
}
intmain()
{
神经网络;
返回0;
}
这就形成了一个包含126个输入、7个输出和两个隐藏层的网络,第一个隐藏层252,第二个隐藏层63个神经元
我推荐了一些你通常会在神经网络中看到的东西
我遇到的问题是初始化网络中的层。m_hiddenLayers
需要使用引用输入层的第一个元素初始化,其余元素使用std::tuple
中的前一项初始化,并且还需要使用正确的类型创建它们,即Neuron
而不是NeuronBase
我怎样才能做到这一点呢?我现在希望有一个。。。钥匙这应该满足您的需求:
template<std::size_t NumInputs, std::size_t NumOutputs, std::size_t... HiddenSizes>
class NeuralNetwork
{
public:
NeuralNetwork()
: m_hiddenLayers{makeHiddenLayers()}
, m_outputLayer{makeOutputLayer()}
{
}
private:
// Creates an array of pointers to each neuron of the input layer
template <std::size_t LayerSize, std::size_t... LayerIdx>
auto makeLayerPtrs(
std::array<InputNeuron, LayerSize> &inputLayer,
std::index_sequence<LayerIdx...>
) {
return std::array<NeuronBase *, LayerSize>{&inputLayer[LayerIdx]...};
}
// Creates an array of pointers to each neuron of the input layer
template <std::size_t LayerSize>
auto makeLayerPtrs(std::array<InputNeuron, LayerSize> &inputLayer) {
return makeLayerPtrs(inputLayer, std::make_index_sequence<LayerSize>{});
}
// Creates an array of pointers to each neuron of the given layer
template <std::size_t LayerSize, std::size_t... LayerIdx>
auto makeLayerPtrs(Layer<LayerSize> &layer, std::index_sequence<LayerIdx...>) {
return std::array<NeuronBase *, LayerSize>{layer.GetNeurons()[LayerIdx].get()...};
}
// Creates an array of pointers to each neuron of the given layer
template <std::size_t LayerSize>
auto makeLayerPtrs(Layer<LayerSize> &layer) {
return makeLayerPtrs(layer, std::make_index_sequence<LayerSize>{});
}
// Creates an array of pointers to each neuron of the given layer
template <std::size_t LayerNumber>
auto makeLayerPtrs() {
if constexpr (LayerNumber == 0) {
return makeLayerPtrs(m_inputLayer);
} else {
return makeLayerPtrs(std::get<LayerNumber - 1>(m_hiddenLayers));
}
}
// Creates a Neuron with the given array of pointers to the previous layer
template <auto Dummy, std::size_t LayerSize>
auto makeNeuron(std::array<NeuronBase *, LayerSize> const &previousLayerPtrs) {
return std::make_unique<Neuron<LayerSize>>(previousLayerPtrs);
}
// Creates one hidden layer
template <std::size_t LayerNumber, std::size_t LayerSize, std::size_t... LayerIdx>
auto makeHiddenLayer(std::index_sequence<LayerIdx...>) {
// Implicit shift to 1-based indexing of hidden layers
auto const previousLayerPtrs = makeLayerPtrs<LayerNumber>();
return Layer<LayerSize>{{makeNeuron<LayerIdx>(previousLayerPtrs)...}};
}
// Creates all of the hidden layers
template <std::size_t... HiddenLayersIdx>
auto makeHiddenLayers(std::index_sequence<HiddenLayersIdx...>) {
return std::tuple{
makeHiddenLayer<HiddenLayersIdx, HiddenSizes>(
std::make_index_sequence<HiddenSizes>{}
)...
};
}
// Creates all of the hidden layers
auto makeHiddenLayers() {
return makeHiddenLayers(std::make_index_sequence<sizeof...(HiddenSizes)>{});
}
// Creates the output layer
template <std::size_t... LayerIdx>
auto makeOutputLayer(std::index_sequence<LayerIdx...>) {
auto const lastHiddenLayerPtrs = makeLayerPtrs<sizeof...(HiddenSizes)>();
return Layer<NumOutputs>{{makeNeuron<LayerIdx>(lastHiddenLayerPtrs)...}};
}
// Creates the output layer
auto makeOutputLayer() {
return makeOutputLayer(std::make_index_sequence<NumOutputs>{});
}
protected:
// Caution : reordered members
std::array<InputNeuron,NumInputs> m_inputLayer;
std::tuple<Layer<HiddenSizes>...> m_hiddenLayers;
Layer<NumOutputs> m_outputLayer;
};
模板
类神经网络
{
公众:
神经网络
:m_hiddenLayers{makeHiddenLayers()}
,m_outputLayer{makeOutputLayer()}
{
}
私人:
//创建指向输入层每个神经元的指针数组
模板
自动生成图层器(
std::阵列和输入层,
std::index_序列
) {
返回std::数组{&inputLayer[LayerIdx]…};
}
//创建指向输入层每个神经元的指针数组
模板
自动生成层rpter(标准::数组和输入层){
返回makelayerpters(inputLayer,std::make_index_sequence{});
}
//创建指向给定层的每个神经元的指针数组
模板
自动生成图层器(图层和图层,标准::索引顺序){
返回std::数组{layer.GetNeurons()[LayerIdx].get()…};
}
//创建指向给定层的每个神经元的指针数组
模板
自动生成图层器(图层和图层){
返回makelayerpters(layer,std::make_index_sequence{});
}
//创建指向给定层的每个神经元的指针数组
模板
自动生成图层器(){
如果constexpr(LayerNumber==0){
返回MakeLayerPters(m_inputLayer);
}否则{
返回makelayerpters(std::get(m_hiddenLayers));
}
}
//使用指向上一层的给定指针数组创建神经元
模板