神经网络结构参数

来源:互联网 发布:蚁群算法和粒子群算法 编辑:程序博客网 时间:2024/05/20 22:27
    在使用神经网络的时候,都需要输入每一个网络层的输入和输出,以及每个网络层的激活函数,为了方便后续根据不同的需要,选择合适的输入输出神经元个数和每一层的激活函数,因此,考虑将神经网络的结构参数单独写成一个类的形式,这样也方便以后进行拓展。



    根据神经网络的结构特点,每一个神经网络层只要知道输入神经元个数,输出神经元个数,以及激活函数即可,因此,神经网络结构参数上面的几个参数。但是,对于如何设计一个好的结构来获得这些参数呢,目前,我的想法是使用一个字典类型的容器来储存这些数据,将每一层的名称作为键值来储存。
    具体实现代码如下:
    neuralnetworksparams.h
/*M///////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, sheng// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:////     * Redistributions of source code must retain the above copyright notice,//       this list of conditions and the following disclaimer.////     * Redistributions in binary form must reproduce the above copyright notice,//       this list of conditions and the following disclaimer in the documentation//       and/or other materials provided with the distribution.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.////M*/#ifndef NEURALNETWORKSPARAMS_H#define NEURALNETWORKSPARAMS_H#include <map>#include <string>class NeuralNetworksParams{    public:        NeuralNetworksParams();        NeuralNetworksParams(const NeuralNetworksParams& RObject);        ~NeuralNetworksParams();        bool AddInputlayerParams(int NumberOfInputUnits,                                 int TypeOfActivationFunction);        int GetNumberOfInputUnits();        int GetAFTypeOfInputlayer();        bool AddOutputlayerParams(int NumberOfOutputUnits,                                  int TypeOfActivationFunction);        int GetNumberOfOutputUnits();        int GetAFTypeOfOutputlayer();        bool AddHiddenlayerParams(int NumberOfUnits,                                  int TypeOfActivationFunction);        int GetNumberOfHiddenUnits(int IndexOfHiddenlayer);        int GetAFTypeOfHiddenlayer(int IndexOfHiddenlayer);        int GetNumberOfHiddenlayers() const;    private:        std::map<std::string, int> Params;        int NumberOfHiddenlayers;        static const std::string INPUTLAYER;        static const std::string OUTPUTLAYER;        static const std::string HIDDENLAYERPREFIX;        static const std::string ACTIVATIONFUNCTIONPREFIX;        bool Insert(const std::string &Key, int Value);        bool IsExist(const std::string& Key);        int GetValueByKey(const std::string& Key);        std::string GetKeyOfInputLayer() const;        std::string GetKeyOfInputLayerAFType() const;        std::string GetKeyOfOutputLayer() const;        std::string GetKeyOfOutputLayerAFType() const;        std::string GetKeyOfHiddenlayer(int Index) const;        std::string GetKeyOfHiddenlayerAFType(int Index) const;};#endif // NEURALNETWORKSPARAMS_H


    neuralnetworksparams.cpp
/*M///////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, sheng// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:////     * Redistributions of source code must retain the above copyright notice,//       this list of conditions and the following disclaimer.////     * Redistributions in binary form must reproduce the above copyright notice,//       this list of conditions and the following disclaimer in the documentation//       and/or other materials provided with the distribution.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.////M*/#include "neuralnetworksparams.h"#include "IntToString.h"const std::string NeuralNetworksParams:: INPUTLAYER = "INPUTLAYER";const std::string NeuralNetworksParams::OUTPUTLAYER = "OUTPUTLAYER";const std::string NeuralNetworksParams::HIDDENLAYERPREFIX = "HIDDENLAYER_";const std::string NeuralNetworksParams::ACTIVATIONFUNCTIONPREFIX = "ACTIVATIONFUNCTION_";/** * @brief NeuralNetworksParams::NeuralNetworksParams The default constructor. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */NeuralNetworksParams::NeuralNetworksParams() : Params(), NumberOfHiddenlayers(0){}/** * @brief NeuralNetworksParams::NeuralNetworksParams The copy constructor * @param RObject The object which is to be copyed. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */NeuralNetworksParams::NeuralNetworksParams(const NeuralNetworksParams &RObject) :    Params(RObject.Params), NumberOfHiddenlayers(RObject.NumberOfHiddenlayers){}/** * @brief NeuralNetworksParams::~NeuralNetworksParams The destructor. * * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */NeuralNetworksParams::~NeuralNetworksParams(){    Params.clear();}/** * @brief NeuralNetworksParams::AddInputlayerParams Add the inputlayer params * @param NumberOfInputUnits   The number of the input units * @param TypeOfActivationFunction The type of the activation function of the *                                 intput layer * @return true if the opartion is successed, *         false otherwise * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */bool NeuralNetworksParams::AddInputlayerParams(int NumberOfInputUnits,                                               int TypeOfActivationFunction){    if (NumberOfInputUnits < 1)    {        return false;    }    bool Result = false;    // insert the number of the input units into the params    std::string Key = GetKeyOfInputLayer();    Result = Insert(Key, NumberOfInputUnits);    // insert the typf of the AF of the input layer    Key = GetKeyOfInputLayerAFType();    Result = Result && Insert(Key, TypeOfActivationFunction);    return Result;}/** * @brief NeuralNetworksParams::GetNumberOfInputUnits Get the number of the *            input layer * * @return The number of the input layer, *         return -1 if the input layer is not exist. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetNumberOfInputUnits(){    std::string Key = GetKeyOfInputLayer();    if (IsExist(Key))    {        return Params[Key];    }    return -1;}/** * @brief NeuralNetworksParams::GetAFTypeOfInputlayer Get the type of the *            activation function of the input layer * @return The type of the activation function of the input layer *         return -1 if the activation function is not exist. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetAFTypeOfInputlayer(){    std::string Key = GetKeyOfInputLayerAFType();    if (IsExist(Key))    {        return Params[Key];    }    return -1;}/** * @brief NeuralNetworksParams::AddOutputlayerParams Add the params of the *            output layer * @param NumberOfOutputUnits The number of the output layer * @param TypeOfActivationFunction The type of the activation function of the *            output layer * @return true if the operation is successed, *         false otherwise * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */bool NeuralNetworksParams::AddOutputlayerParams(int NumberOfOutputUnits,                                                int TypeOfActivationFunction){    if (NumberOfOutputUnits < 1)    {        return false;    }    bool Result = false;    // insert the number of the output layer    std::string Key = GetKeyOfOutputLayer();    Result = Insert(Key, NumberOfOutputUnits);    // insert the type of the actinvation function of the outpue layer    Key = GetKeyOfOutputLayerAFType();    Result = Result && Insert(Key, TypeOfActivationFunction);    return Result;}/** * @brief NeuralNetworksParams::GetNumberOfOutputUnits Get the number of the *            output units * @return The number of the output units, *         return -1 if the output layer is not exist. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetNumberOfOutputUnits(){    std::string Key = GetKeyOfOutputLayer();    return GetValueByKey(Key);}/** * @brief NeuralNetworksParams::GetAFTypeOfOutputlayer Get the tyep of the *            activation function of the output layer. * @return The type of the activation function of the output layer. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetAFTypeOfOutputlayer(){    std::string Key = GetKeyOfOutputLayerAFType();    return GetValueByKey(Key);}/** * @brief NeuralNetworksParams::AddHiddenlayerParams Add the params of the *            hidden layer. * @param NumberOfUnits The number of the units in the hidden layer * @param TypeOfActivationFunction The type of the activation function of the *            hidden layer * @return true if the operation is successed, *         false otherwise. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */bool NeuralNetworksParams::AddHiddenlayerParams(int NumberOfUnits,                                                int TypeOfActivationFunction){    if (NumberOfUnits < 1)    {        return false;    }    bool Result = false;    // insert the number of the units of the hidden layer    std::string Key = GetKeyOfHiddenlayer(NumberOfHiddenlayers);    Result = Insert(Key, NumberOfUnits);    // insert the type of the activation function of the hidden layer    Key = GetKeyOfHiddenlayerAFType(NumberOfHiddenlayers);    Result = Result && Insert(Key, TypeOfActivationFunction);    if (Result)    {        NumberOfHiddenlayers++;    }    return Result;}/** * @brief NeuralNetworksParams::GetNumberOfHiddenUnits Get the number of the *            units of the No.Index layer * @param IndexOfHiddenlayer The 0-base index of the hidden layer * @return  The number of the No.Index hidden layer *          return -1 if the hidden layer is not exist. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetNumberOfHiddenUnits(int IndexOfHiddenlayer){    if ((IndexOfHiddenlayer < 0) || (IndexOfHiddenlayer > NumberOfHiddenlayers))    {        return -1;    }    // get the number of the units of the hidden layer    std::string Key = GetKeyOfHiddenlayer(IndexOfHiddenlayer);    return GetValueByKey(Key);}/** * @brief NeuralNetworksParams::GetAFTypeOfHiddenlayer Get the type of the *            activation function of the No.Index hidden layer * @param IndexOfHiddenlayer The index of the hidden layer * @return The type of the activaiton function of the hidden layer *         return -1 if the operation is failed. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetAFTypeOfHiddenlayer(int IndexOfHiddenlayer){    if ((IndexOfHiddenlayer < 0) || (IndexOfHiddenlayer > NumberOfHiddenlayers))    {        return -1;    }    // get the type of the activation function of the hidden layer    std::string Key = GetKeyOfHiddenlayerAFType(IndexOfHiddenlayer);    return GetValueByKey(Key);}/** * @brief NeuralNetworksParams::GetNumberOfHiddenlayers Get the number of the *            hidden layer * @return The number of the hidden layer; * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetNumberOfHiddenlayers() const{    return NumberOfHiddenlayers;}/** * @brief NeuralNetworksParams::Insert Insert the element to the params * @param Key  The key of the elememt * @param Value The value of the elememt * @return true if the operation is successed *         false otherwise * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */bool NeuralNetworksParams::Insert(const std::string &Key, int Value){    // return false if the value is negative.    if (Value < 0)    {        return false;    }    Params[Key] = Value;    return true;}/** * @brief NeuralNetworksParams::IsExist check if the element of the given key is *             exist. * @param Key The key of the element. * @return true if the element is exist. *         false otherwise * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */bool NeuralNetworksParams::IsExist(const std::string &Key){    // find the element    std::map<std::string, int>::iterator Ite = Params.find(Key);    // return true when the element is exist in the params    if (Ite != Params.end())    {        return true;    }    return false;}/** * @brief NeuralNetworksParams::GetValueByKey Get the value of the element of *            the given key * @param Key The key of the element * @return The value of the element, *         return -1 if the element is not exist. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */int NeuralNetworksParams::GetValueByKey(const std::string &Key){    // return the value if the element is exist.    if (IsExist(Key))    {        return Params[Key];    }    return -1;}/** * @brief NeuralNetworksParams::GetKeyOfInputLayer Get the key of the input *            layer. * @return The key of the input layer * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfInputLayer() const{    return INPUTLAYER;}/** * @brief NeuralNetworksParams::GetKeyOfInputLayerAFType Get the key of the *             activation function of the input layer * @return The key of the AF type of the input layer * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfInputLayerAFType() const{    std::string Result = INPUTLAYER + ACTIVATIONFUNCTIONPREFIX;    return Result;}/** * @brief NeuralNetworksParams::GetKeyOfOutputLayer Get the key of the output *            layer. * @return The key of the output layer. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfOutputLayer() const{    return OUTPUTLAYER;}/** * @brief NeuralNetworksParams::GetKeyOfOutputLayerAFType Get the key of the *           type of the activation function of the output layer. * @return The key of the type of the AF of the output layer. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfOutputLayerAFType() const{    std::string Result = OUTPUTLAYER + ACTIVATIONFUNCTIONPREFIX;    return Result;}/** * @brief NeuralNetworksParams::GetKeyOfHiddenlayer Get the key of the No.Index *            hidden layer. * @param Index The 0-base index of the hidden layer. * @return The key of the No.Index  hidden layer * * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfHiddenlayer(int Index) const{    std::string Result = IntToString(Index);    Result = HIDDENLAYERPREFIX + Result;    return Result;}/** * @brief NeuralNetworksParams::GetKeyOfHiddenlayerAFType Get the key of the *            type of the activation function of the No.Index layer. * @param Index The 0-base index of the hidden layer * @return The key of the type of the No.Index hidden layer. * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng        2014-09-10         0.1          build the module * */std::string NeuralNetworksParams::GetKeyOfHiddenlayerAFType(int Index) const{    std::string Result = IntToString(Index);    Result = HIDDENLAYERPREFIX + ACTIVATIONFUNCTIONPREFIX + Result;    return Result;}


    Test_NeuralNetworkParams.cpp
/*M///////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, sheng// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:////     * Redistributions of source code must retain the above copyright notice,//       this list of conditions and the following disclaimer.////     * Redistributions in binary form must reproduce the above copyright notice,//       this list of conditions and the following disclaimer in the documentation//       and/or other materials provided with the distribution.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.////M*/#include "neuralnetworksparams.h"#include "TypeDefinition.h"#include <iostream>/** * @brief Test_NeuralNetworksParams * * @author sheng * @date   2014-09-10 * @version 0.1 * * @history *     <author>       <date>         <version>        <description> *      sheng       2014-09-10          0.1         build the module * */void Test_NeuralNetworksParams(){    //    NeuralNetworksParams Params;    Params.AddInputlayerParams(10, LINEAR);    Params.AddHiddenlayerParams(20, SIGMOID);    Params.AddHiddenlayerParams(50, TANH);    Params.AddOutputlayerParams(2, RELU);    std::cout << "The number of units of input layer is " <<                 Params.GetNumberOfInputUnits() << std::endl;    std::cout << "The type of the input layer is " <<                 Params.GetAFTypeOfInputlayer() << std::endl;    std::cout << "The number of units of outpue layer is " <<                 Params.GetNumberOfOutputUnits() << std::endl;    std::cout << "The type of the output layer is " <<                 Params.GetAFTypeOfOutputlayer() << std::endl;    std::cout << "The number of units of 0 hidden layer is " <<                 Params.GetNumberOfHiddenUnits(0) << std::endl;    std::cout << "The type of the 0 hidden layer is " <<                 Params.GetAFTypeOfHiddenlayer(0) << std::endl;    std::cout << "The number of units of 1 hidden layer is " <<                 Params.GetNumberOfHiddenUnits(1) << std::endl;    std::cout << "The type of the 1 hidden layer is " <<                 Params.GetAFTypeOfHiddenlayer(1) << std::endl;    std::cout << "The number of units of 2 hidden layer is " <<                 Params.GetNumberOfHiddenUnits(2) << std::endl;    std::cout << "The type of the 2 hidden layer is " <<                 Params.GetAFTypeOfHiddenlayer(2) << std::endl;    std::cout << "The number of the hidden layer is " <<                 Params.GetNumberOfHiddenlayers() << std::endl;    //    NeuralNetworksParams Params1;    Params1.AddInputlayerParams(0, LINEAR);    Params1.AddHiddenlayerParams(0, SIGMOID);    Params1.AddHiddenlayerParams(0, TANH);    Params1.AddOutputlayerParams(0, RELU);    std::cout << "The number of units of input layer is " <<                 Params1.GetNumberOfInputUnits() << std::endl;    std::cout << "The type of the input layer is " <<                 Params1.GetAFTypeOfInputlayer() << std::endl;    std::cout << "The number of units of outpue layer is " <<                 Params1.GetNumberOfOutputUnits() << std::endl;    std::cout << "The type of the output layer is " <<                 Params1.GetAFTypeOfOutputlayer() << std::endl;    std::cout << "The number of units of 0 hidden layer is " <<                 Params1.GetNumberOfHiddenUnits(0) << std::endl;    std::cout << "The type of the 0 hidden layer is " <<                 Params1.GetAFTypeOfHiddenlayer(0) << std::endl;    std::cout << "The number of units of 1 hidden layer is " <<                 Params1.GetNumberOfHiddenUnits(1) << std::endl;    std::cout << "The type of the 1 hidden layer is " <<                 Params1.GetAFTypeOfHiddenlayer(1) << std::endl;    std::cout << "The number of units of 2 hidden layer is " <<                 Params1.GetNumberOfHiddenUnits(2) << std::endl;    std::cout << "The type of the 2 hidden layer is " <<                 Params1.GetAFTypeOfHiddenlayer(2) << std::endl;    std::cout << "The number of the hidden layer is " <<                 Params1.GetNumberOfHiddenlayers() << std::endl;}


    



github地址:https://github.com/shengno/NeuralNetworksParams
版权所有,欢迎转载,转载请注明出处,谢谢微笑













    
0 0
原创粉丝点击