gvector.cpp
来自「一个由Mike Gashler完成的机器学习方面的includes neural」· C++ 代码 · 共 292 行
CPP
292 行
/* Copyright (C) 2006, Mike Gashler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. see http://www.gnu.org/copyleft/lesser.html*/#include "GVector.h"#include <stdio.h>#include <string.h>#include <math.h>#include "GBits.h"#include "GMacros.h"// staticdouble GVector::ComputeDotProduct(const double* pA, const double* pB, int nSize){ int n; double dVal = 0; for(n = 0; n < nSize; n++) dVal += pA[n] * pB[n]; return dVal;}// staticdouble GVector::ComputeDotProduct(const double* pOrigin, const double* pTarget, const double* pVector, int nSize){ int n; double dVal = 0; for(n = 0; n < nSize; n++) dVal += (pTarget[n] - pOrigin[n]) * pVector[n]; return dVal;}// staticdouble GVector::ComputeSquaredDistance(double* pA, double* pB, int nSize){ double dist = 0; double d; int n; for(n = 0; n < nSize; n++) { d = pA[n] - pB[n]; dist += (d * d); } return dist;}// staticdouble GVector::ComputeSquaredMagnitude(const double* pVector, int nSize){ double dMag = 0; int i; for(i = 0; i < nSize; i++) dMag += (pVector[i] * pVector[i]); return dMag;}// staticdouble GVector::LNormComputeMagnitude(double l, const double* pVector, int nSize){ double dMag = 0; int i; for(i = 0; i < nSize; i++) dMag += pow(ABS(pVector[i]), l); return pow(dMag, 1.0 / l);}// staticdouble GVector::ComputeCorrelation(const double* pA, const double* pB, int nDims){ double dDotProd = ComputeDotProduct(pA, pB, nDims); if(dDotProd == 0) return 0; return dDotProd / (sqrt(ComputeSquaredMagnitude(pA, nDims)) * sqrt(ComputeSquaredMagnitude(pB, nDims)));}// staticvoid GVector::Normalize(double* pVector, int nSize){ double dMag = sqrt(ComputeSquaredMagnitude(pVector, nSize)); int i; for(i = 0; i < nSize; i++) pVector[i] /= dMag;}// staticvoid GVector::LNormNormalize(double l, double* pVector, int nSize){ double dMag = LNormComputeMagnitude(l, pVector, nSize); int i; for(i = 0; i < nSize; i++) pVector[i] /= dMag;}// staticint GVector::FindMax(double* pVector, int nSize){ int nIndex = rand() % nSize; int n; for(n = 0; n < nSize; n++) { if(pVector[n] > pVector[nIndex]) nIndex = n; } return nIndex;}// staticvoid GVector::GetRandomVector(double* pOutVector, int nSize){ int i; for(i = 0; i < nSize; i++) pOutVector[i] = GBits::GetRandomGaussian(); Normalize(pOutVector, nSize);}// staticbool GVector::TestPivot(double* pCenter, double* pNormal, double* pVector, int nDims){ int n; double dVal = 0; for(n = 0; n < nDims; n++) dVal += (pVector[n] - pCenter[n]) * pNormal[n]; return dVal >= 0;}// staticvoid GVector::Add(double* pDest, double* pSource, int nDims){ int i; for(i = 0; i < nDims; i++) pDest[i] += pSource[i];}// staticvoid GVector::Subtract(double* pDest, double* pSource, int nDims){ int i; for(i = 0; i < nDims; i++) pDest[i] -= pSource[i];}// staticvoid GVector::Multiply(double* pVector, double dScalar, int nDims){ int i; for(i = 0; i < nDims; i++) pVector[i] *= dScalar;}// staticvoid GVector::SetToZero(double* pVector, int nDims){ int i; for(i = 0; i < nDims; i++) pVector[i] = 0;}void GVector::GetMostEccentricMaxs(int* pOutPoints, int nPoints, bool bMax, double* pVector, int nDims){ if(nPoints < 1) return; // Handle the case where we don't have enough points int i; if(nDims <= nPoints) { for(i = 0; i < nPoints; i++) pOutPoints[i] = i * nDims / nPoints; return; } // Find the most eccentric of the eccentric points until we have fewer than we need int nSign = bMax ? 1 : -1; GTEMPBUF(int, pWorkBuffers, nDims * 2); int* pPrev = &pWorkBuffers[nDims]; int* pCurrent = pWorkBuffers; for(i = 0; i < nDims; i++) pCurrent[i] = i; int nPointCount = nDims; int nPrevPointCount = 0; int a, b, c, nPos, maxGap; while(nPointCount > nPoints) { // Swap the buffers int* pTemp = pPrev; pPrev = pCurrent; pCurrent = pTemp; // Compute the max gap maxGap = nDims * 5 / nPointCount; // 5 is the max allowed gap ratio. Smaller values restrict to more even-ness (and increase computation time) // Find all the local maxes nPos = 0; a = pPrev[0]; b = pPrev[1]; if(b - a > maxGap || (pVector[a] - pVector[b]) * nSign > 0) pCurrent[nPos++] = a; for(i = 1; i < nPointCount - 1; i++) { a = pPrev[i - 1]; b = pPrev[i]; c = pPrev[i + 1]; if(b - a > maxGap || c - b > maxGap || GBits::GetSign((pVector[b] - pVector[a]) * nSign) + GBits::GetSign((pVector[b] - pVector[c]) * nSign) > 0) pCurrent[nPos++] = b; } a = pPrev[i - 1]; b = pPrev[i]; if(b - a > maxGap || (pVector[b] - pVector[a]) * nSign > 0) pCurrent[nPos++] = b; nPrevPointCount = nPointCount; nPointCount = nPos; } // Use all the points in pCurrent and some of the points in pPrev GAssert(nPointCount <= nPoints && nPrevPointCount > nPoints, "unexpected array sizes"); nPos = 0; int nPrevPos = 0; int nNeeded; for(i = 0; i < nPoints; i++) { // Skip excess points in pPrev nNeeded = nPoints - i; while( (nPos >= nPointCount || pPrev[nPrevPos] != pCurrent[nPos]) && nPrevPointCount - nPrevPos > nNeeded && i * nPrevPointCount / nPoints > nPrevPos ) nPrevPos++; // Take the next point pOutPoints[i] = pPrev[nPrevPos]; if(nPos < nPointCount && pCurrent[nPos] == pPrev[nPrevPos]) nPos++; nPrevPos++; }}void GVector::GetMostEccentricPoints(int* pOutPoints, int nPoints, double* pVector, int nDims){ // Get a set of maxs and a set of mins int nMins = nPoints / 2; int nMaxs = nMins; if(nMaxs + nMins < nPoints) nMaxs++; GTEMPBUF(int, pMaxs, nPoints); int* pMins = &pMaxs[nMaxs]; GVector::GetMostEccentricMaxs(pMaxs, nMaxs, true, pVector, nDims); GVector::GetMostEccentricMaxs(pMins, nMins, false, pVector, nDims); // Merge the points int i; int nMaxPos = 0; int nMinPos = 0; for(i = 0; i < nPoints; i++) { if(nMaxPos >= nMaxs) pOutPoints[i] = pMins[nMinPos++]; else if(nMinPos >= nMins) pOutPoints[i] = pMaxs[nMaxPos++]; else if(pMins[nMinPos] < pMaxs[nMaxPos]) pOutPoints[i] = pMins[nMinPos++]; else pOutPoints[i] = pMaxs[nMaxPos++]; }}void GVector::InterpolateIndexes(int nIndexes, double* pInIndexes, double* pOutIndexes, float fRatio, int nCorrIndexes, double* pCorrIndexes1, double* pCorrIndexes2){ GAssert(nCorrIndexes >= 2, "need at least two correlated indexes (at least the two extremes)"); int nCorr = 0; double fInvRatio = (float)1 - fRatio; double fIndex, fWeight, f0, f1; int i; for(i = 0; i < nIndexes; i++) { fIndex = pInIndexes[i]; while(nCorr < nCorrIndexes - 2 && fIndex >= pCorrIndexes1[nCorr + 1]) nCorr++; fWeight = (fIndex - pCorrIndexes1[nCorr]) / (pCorrIndexes1[nCorr + 1] - pCorrIndexes1[nCorr]); f0 = fInvRatio * pCorrIndexes1[nCorr] + fRatio * pCorrIndexes2[nCorr]; f1 = fInvRatio * pCorrIndexes1[nCorr + 1] + fRatio * pCorrIndexes2[nCorr + 1]; pOutIndexes[i] = ((float)1 - fWeight) * f0 + fWeight * f1; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?