Я пытаюсь написать программу, которая даст мне пропускную способность для перекрестной проверки оценщика ядра в c ++ (около 20 000 точек данных, поэтому Matlab слишком медленный). Я делаю это, используя секущий алгоритм на производной от цели оценки «оставь один». Моя проблема заключается в том, что эта функция принимает в качестве аргументов данные, которые извлекаются в основной функции из файла CSV.
Одним из аргументов алгоритма секванса является функция, которая принимает удвоение и возвращает удвоение, но функция, которую я написал для производной цели, должна принимать целый ряд других дерьмов, которые математически мы "Рассмотрим параметры (такие как данные, выбор функции ядра и т. д.).
Мне нужно иметь возможность написать функцию, которая использует функцию, определяющую цель, помещает данные, которые основная функция извлекает из файла, и принимает в качестве единственного ввода двойную переменную. Есть ли способ сделать это?
double cvobjective(double data[], int n, double (*k)(double), double (*kd)(double), double h)
{
double cvob = 0;
double xi;
double xj;
for(int i = 0; i < n; ++i)
{
xi = data[i];
double sumki = 0;
double sumkdi = 0;
for(int j = 0; j < n; ++j) //find sum of k((xj-xi)/h) and k'((xj-xi)/h)*(xj-xi)
{
xj = data[j];
sumki = sumki + k((xj-xi)/h);
sumkdi = sumkdi + kd((xj-xi)/h)*(xj-xi);
}
sumki = sumki-k(0);//gets rid of the terms where i=j
sumkdi = sumkdi-kd(0);
cvob = cvob - reciprocal(sumki)*(reciprocal(h)*sumki+reciprocal(pow(h,2))*sumkdi);
}
return cvob;
}
double secantmethod(double (*obj)(double), double init, double tolerance, int giveup)
{
double x = init;
double old = init+1;
double newp;
double fold = obj(old);
double fnew;
for(int i=0;i<giveup;++i)
{
fnew = obj(x);
if(abs(fnew-fold)<tolerance)
{
cout << "Objective values get too close after " << i << " iterations." << endl;
break;
}
newp = newp - (x-old)*reciprocal(fnew-fold)*fnew;
old = x;
x = newp;
cout << "Estimate is currently: " << x << endl;
fold = fnew;
if(abs(fnew)<tolerance)
break;
if(i == giveup - 1)
cout << "Secant algorithm did not converge." << endl;
}
return newp;
}
int main()
{
const int N = 19107;
double incomes[N];
std::ifstream ifile("incomes.csv", std::ios::in);
std::vector<double> scores;
//check to see that the file was opened correctly:
if (!ifile.is_open()) {
std::cerr << "There was a problem opening the input file.\n";
exit(1);//exit or do additional error checking
}
double num = 0.0;
//keep storing values from the text file so long as data exists:
while (ifile >> num) {
scores.push_back(num);
}
//verify that the scores were stored correctly:
for (int i = 0; i < scores.size(); ++i) {
incomes[i]=scores[i];
}
double sv = silverman(incomes,N);
double cvbandwidth = secantmethod(cvobj,sv,0.000001,100);
cout << setprecision(10) << cvbandwidth << endl;
return 0;
}
Очевидно, я пропустил часть кода для более периферийных функций, которые не важны. Я подумал о том, можно ли изменить алгоритм secantmethod так, чтобы он ожидал, что в качестве входных данных будет использована функция, которая имеет в качестве входных данных все, что имеет cvobjective, но мне не сразу было понятно, как я это сделаю,
В идеале я бы мог создать функцию внутри main, чтобы массив доходности входил в сферу действия этой функции, но либо я не правильно понимаю лямбды, либо они не особенно подходят для этогоцель. В противном случае, если есть способ изменить secantmethod описанным выше способом, это также сработает.
EDIT: В приведенном выше cvobj не определен и в настоящее время служит в качестве заполнителя. Мне бы хотелось, чтобы это было что-то вроде
double cvobj(double h)
return cvobjective(incomes,N,normpdf,normpdfdiff,h);
, но, очевидно, когда я пытаюсь это сделать, он жалуется, что доходы и N не входят в сферу действия функции.