Boost를 사용하여 C ++에서 샘플 벡터의 평균 및 표준 계산 계산
부스트를 사용하여 샘플을 포함하는 벡터에 대한 평균 및 표준을 계산하는 방법이 있습니까?
아니면 누산기를 만들고 벡터를 그 안에 넣어야합니까?
를 사용하는 축전지 [해석] 입니다 수단과 표준 편차를 계산하는 방법 부스트 .
accumulator_set<double, stats<tag::variance> > acc;
for_each(a_vec.begin(), a_vec.end(), bind<void>(ref(acc), _1));
cout << mean(acc) << endl;
cout << sqrt(variance(acc)) << endl;
Boost에 더 구체적인 기능이 있는지는 모르겠지만 표준 라이브러리로 할 수 있습니다.
주어지면 std::vector<double> v
이것은 순진한 방법입니다.
#include <numeric>
double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();
double sq_sum = std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size() - mean * mean);
이 크거나 작은 값에 대해 오버플로 또는 언더 플로되기에 대해. 표준 방법을 계산하는 약간 더 나은 방법은 다음과 같습니다.
double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();
std::vector<double> diff(v.size());
std::transform(v.begin(), v.end(), diff.begin(),
std::bind2nd(std::minus<double>(), mean));
double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size());
C ++ 11 업데이트 :
그리고 std::transform
대신 람다 함수를 사용하여에, 대한 호출을 작성할 수 있습니다 (현재 사용되지 않음).std::minus
std::bind2nd
std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });
성능이 중요하고 컴파일러가 람다를 지원하는 경우 stdev 계산을 더 쉽고 간단하게 만들 수 있습니다. VS 2012를 사용하여 다음 코드가 선택에 해당되는 Boost 코드보다 10 배 이상 빠르다는 것을 발견했습니다. ; musiphil에서 제공하는 표준 라이브러리를 사용하는보다 안전한 버전의 답변보다 5 배 빠 사용합니다.
참고 저는 표준 표준 표준을 사용하고 있으므로 아래 코드는 약간 다른 결과를 제공합니다 ( 표준에 마이너스 1이 이유 ).
double sum = std::accumulate(std::begin(v), std::end(v), 0.0);
double m = sum / v.size();
double accum = 0.0;
std::for_each (std::begin(v), std::end(v), [&](const double d) {
accum += (d - m) * (d - m);
});
double stdev = sqrt(accum / (v.size()-1));
musiphil의 답변을 개선 하면 C ++ 11 람다 기능이 diff
있는 단일 inner_product
호출을 사용하여 임시 벡터없이 표준 편차 함수를 작성할 수 있습니다 .
double stddev(std::vector<double> const & func)
{
double mean = std::accumulate(func.begin(), func.end(), 0.0) / func.size();
double sq_sum = std::inner_product(func.begin(), func.end(), func.begin(), 0.0,
[](double const & x, double const & y) { return x + y; },
[mean](double const & x, double const & y) { return (x - mean)*(y - mean); });
return std::sqrt(sq_sum / ( func.size() - 1 ));
}
뺄셈을 여러 번 수행하는 것이 추가 중간 저장소를 사용하는 것보다 저렴하다고 생각하고 더 읽기 쉽다고 생각하지만 아직 성능을 테스트하지 않았습니다.
내 대답은 Josh Greifer와 비슷하지만 표본 공분산으로 일반화되었습니다. 표본 분산은 표본 공분산이지만 두 입력이 동일합니다. 여기에는 Bessel의 상관 관계가 포함됩니다.
template <class Iter> typename Iter::value_type cov(const Iter &x, const Iter &y)
{
double sum_x = std::accumulate(std::begin(x), std::end(x), 0.0);
double sum_y = std::accumulate(std::begin(y), std::end(y), 0.0);
double mx = sum_x / x.size();
double my = sum_y / y.size();
double accum = 0.0;
for (auto i = 0; i < x.size(); i++)
{
accum += (x.at(i) - mx) * (y.at(i) - my);
}
return accum / (x.size() - 1);
}
앞서 언급 한 버전보다 2 배 빠릅니다. 대부분 transform () 및 inner_product () 루프가 결합되어 있기 때문입니다. 내 바로 가기 / typedefs / 매크로 죄송합니다 : Flo = float. CR const ref. VFlo-벡터. VS2010에서 테스트 됨
#define fe(EL, CONTAINER) for each (auto EL in CONTAINER) //VS2010
Flo stdDev(VFlo CR crVec) {
SZ n = crVec.size(); if (n < 2) return 0.0f;
Flo fSqSum = 0.0f, fSum = 0.0f;
fe(f, crVec) fSqSum += f * f; // EDIT: was Cit(VFlo, crVec) {
fe(f, crVec) fSum += f;
Flo fSumSq = fSum * fSum;
Flo fSumSqDivN = fSumSq / n;
Flo fSubSqSum = fSqSum - fSumSqDivN;
Flo fPreSqrt = fSubSqSum / (n - 1);
return sqrt(fPreSqrt);
}
오랫동안 사용되어 왔지만 다음과 같은 우아한 재귀 솔루션은 언급되지 않은 것 같습니다. Knuth의 컴퓨터 프로그래밍 기술을 언급하면,
mean_1 = x_1, variance_1 = 0; //initial conditions; edge case;
//for k >= 2,
mean_k = mean_k-1 + (x_k - mean_k-1) / k;
variance_k = variance_k-1 + (x_k - mean_k-1) * (x_k - mean_k);
n>=2
값 목록 의 경우 표준 편차의 추정치는 다음과 같습니다.
std = variance_n / (n-1).
도움이 되었기를 바랍니다!
고유 한 컨테이너를 만듭니다.
template <class T>
class statList : public std::list<T>
{
public:
statList() : std::list<T>::list() {}
~statList() {}
T mean() {
return accumulate(begin(),end(),0.0)/size();
}
T stddev() {
T diff_sum = 0;
T m = mean();
for(iterator it= begin(); it != end(); ++it)
diff_sum += ((*it - m)*(*it -m));
return diff_sum/size();
}
};
몇 가지 제한 사항이 있지만 수행중인 작업을 알 때 아름답게 작동합니다.
// C ++의 편차를 의미합니다.
/ 관찰 된 값과 관심 수량의 실제 값 (예 : 모집단 평균) 간의 차이 인 편차는 오류이며 관측 된 값과 실제 값의 추정치 (예 : 추정치는 표본 평균 일 수 있음)은 잔차입니다. 이러한 개념은 측정 간격 및 비율 수준의 데이터에 적용 할 수 있습니다. /
#include <iostream>
#include <conio.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv)
{
int i,cnt;
cout<<"please inter count:\t";
cin>>cnt;
float *num=new float [cnt];
float *s=new float [cnt];
float sum=0,ave,M,M_D;
for(i=0;i<cnt;i++)
{
cin>>num[i];
sum+=num[i];
}
ave=sum/cnt;
for(i=0;i<cnt;i++)
{
s[i]=ave-num[i];
if(s[i]<0)
{
s[i]=s[i]*(-1);
}
cout<<"\n|ave - number| = "<<s[i];
M+=s[i];
}
M_D=M/cnt;
cout<<"\n\n Average: "<<ave;
cout<<"\n M.D(Mean Deviation): "<<M_D;
getch();
return 0;
}
'IT' 카테고리의 다른 글
Java 8 Streams FlatMap 메서드 예제 (0) | 2020.09.17 |
---|---|
HTML 테이블에서 열을 숨기는 방법은 무엇입니까? (0) | 2020.09.17 |
각도 2의 배열에서 항목 제거 (0) | 2020.09.17 |
Meteor 게시 / 구독 이해 (0) | 2020.09.17 |
괄호 사이에 텍스트를 반환하는 정규식 (0) | 2020.09.17 |