1

C++ 用の dlib 最適化ライブラリ、特に次の関数を使用しています。

template <
    typename search_strategy_type,
    typename stop_strategy_type,
    typename funct, 
    typename funct_der, 
    typename T
    >
double find_max (
    search_strategy_type search_strategy,
    stop_strategy_type stop_strategy,
    const funct& f, 
    const funct_der& der, 
    T& x, 
    double max_f
);

関数 f と der は、my 関数の最大値を取得するために変更されるデータ パラメーターのベクトルを取得するように設計されています。ただし、最大化されている関数には 4 つのパラメーターがあります (1 つは私のデータセットで、もう 1 つは私が修正したものです)。ただし、これらの形式が想定されているため、これらを f および der 関数への入力として渡すことはできません。このデータを関数に取り込むにはどうすればよいですか? 現在、以下を試しています(変数 c をハード設定しましたが、ベクトル xgrequ の場合、関数を処理するたびにファイルからデータを読み取ります。

//Function to be minimized
double mleGPD(const column_vector& p)
{
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    double nu = xgrequ.size();
    double sum = 0.0;
    double a = p(0);
    double b = p(1);

    for (unsigned h = 0; h < nu; ++h)
    {
        sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
    }
    return sum;
}
//Derivative of function to be minimized
const column_vector mleGPDDer(const column_vector& p)
{
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    column_vector res(2);
    const double a = p(0);
    const double b = p(1);
    double nu = xgrequ.size();
    double sum1 = 0.0;
    double sum2 = 0.0;
    for (unsigned h = 0; h < nu; ++h)
    {
        sum1 += ((xgrequ[h]-c)/b)/(1-a*((xgrequ[h]-c)/b));
        sum2 += log(1 - a*((xgrequ[h] - c) / b));
    }
    res(0) = sum1;//df/da
    res(1) = sum2;//df/db
    return res;
}

私の実際の関数呼び出しは次のようになります。

//Dlib max finding
    column_vector start(2);
    start = .1, .1; //starting point for a and b
    find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), mleGPD, mleGPDDer, start,100);
    std::cout << "solution" << start << std::endl;
4

1 に答える 1

0

この種の API は非常に一般的です。ほとんどの場合、静的関数だけでなく、任意のcallablefに対して forおよびto を実行できます。つまり、演算子 () を使用してカスタム クラス オブジェクトを渡すことができます。der

例えば

struct MyF {
  //int m_state; 
  //   or other state variables, such as 
  std::vector<double> m_histRet;
  // (default constructors will do)

  double operator()(const column_vector& p) const {
    return some_function_of(p, m_state);
  }
};

int main(){
  . . . 
  MyF myf{42};
  // or
  MyF myf{someVectorContainingHistRet};

  // then use myf as you would have used mleGPD
}

MyF と MyDer を同じ状態で開始する必要があります (std::vector<double> histRet私は推測します)。同じ状態へのコピーまたは (const) 参照として。

編集:より完全な例:

struct MLGDPG_State {
  std::vector<double> xgrequ;
  // . . . and more you need in f or fder
}

MLGDPG_State makeMLGDPG_State(const std::string& filename){
    std::ifstream infile(filename);
    std::ifstream infile("Xm-EVT.csv");
    long double swapRet;
    std::string closeStr;
    std::vector<double> histRet;

    //Read in historical swap data file
    if (infile.is_open())
    {
        while (!infile.eof())
        {
            infile >> swapRet;
            histRet.push_back(swapRet);
        }
    }
    sort(histRet.begin(), histRet.end());
    std::vector<double> negRet;
    //separate out losses
    for (unsigned c = 0; c < histRet.size(); c++)
    {
        if (histRet[c] < 0)
        {
            negRet.push_back(histRet[c]);
        }
    }
    std::vector<double> absValRet;
    //make all losses positive to fit with EVT convention
    for (unsigned s = 0; s < negRet.size(); s++)
    {
        absValRet.push_back(abs(negRet[s]));
    }
    std::vector<double> xminusu, xmu, xgrequ;
    int count = absValRet.size();
    double uPercent = .9;
    int uValIndex = ceil((1 - uPercent)*count);
    int countAbove = count - uValIndex;
    double c = (double)absValRet[uValIndex - 1];
    //looking at returns above u
    for (unsigned o = 0; o < uValIndex; ++o)
    {
        xmu.push_back(absValRet[o] - c);
        if (xmu[o] >= 0)
        {
            xgrequ.push_back(absValRet[o]);
            xminusu.push_back(xmu[o]);
        }
    }
    return {std::move(xgrequ)}; 
    // Or just 'return MleGPD(xgrequ)' if you are scared of {} and move
}

//Functor Class, for ion to be minimized
struct MleGPD{
  MLGDPG_State state;  
  double operator()(const column_vector& p) const {   
    auto mu = state.xgrequ.size();
    double sum = 0.0;
    double a = p(0);
    double b = p(1);
    for (unsigned h = 0; h < nu; ++h)
    {
        sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
    }
    return sum;
};

struct にも同じパターンを使用しMleGPD_Derivativeます。

使用法:

const auto state = makeMLGDPG_State("Xm-EVT.csv");
const auto f = MleGPD{state};
const auto der = MleGPD_Derivative{state};

start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), f, der, start,100);
std::cout << "solution" << start << std::endl;

これらのような単純な構造体の場合、多くの場合、デフォルトのコンストラクター、コピー コンストラクターなどを使用しても問題ないことに注意してください。 http://en.cppreference.com/w/cpp/language/aggregate_initializationにも注意してください。

于 2015-11-08T17:37:03.463 に答える