manifold.cpp

来自「一个由Mike Gashler完成的机器学习方面的includes neural」· C++ 代码 · 共 1,682 行 · 第 1/5 页

CPP
1,682
字号
			searcher.Iterate();
			d = critic.GetBestError();
			if(d < dBest)
			{
				dBest = d;
				i = 0;
			}
			else
			{
				i++;
				if(i > 1000)
					break;
			}
			//printf("Error: %f\n", d);
		}
		double* pBestVec = critic.GetBestYet();
		//printf("Scale=%f, Add=%f\n", pBestVec[0], pBestVec[1]);
		//printf("order errors: %d\n", MeasureSingleDimOrderErrors());
		return critic.GetBestError();
	}
};



double LengthOfSineFunc(double x)
{
	double d = cos(x);
	return sqrt(d * d + 1.0);
}

double LengthOfSwissRoll(double x)
{
#ifdef WIN32
	GAssert(false, "not implemented yet for Win32");
	return 0;
#else
	return (x * sqrt(x * x + 1) + asinh(x)) / 2;
#endif
}

class SwissRollModel : public ManifoldModel
{
protected:

public:
	enum ManifoldType
	{
		SWISS_ROLL,
		S_CURVE,
		SPIRALS,
	};

	SwissRollModel(ManifoldType eType, int nPoints, bool bMask, int nNeighbors, double dSquishingRate, bool bComputeIdeal, int nSupervisedPoints, SwissRollModel* pTrainedModel) : ManifoldModel()
	{
		// Make the relation
		m_pRelation = new GArffRelation();
		m_pRelation->AddAttribute(new GArffAttribute(true, 0, NULL)); // x
		m_pRelation->AddAttribute(new GArffAttribute(true, 0, NULL)); // y
		m_pRelation->AddAttribute(new GArffAttribute(true, 0, NULL)); // z

		// Make the ARFF data
		if(bComputeIdeal)
			m_pIdealResults = new double[nPoints * (eType == SPIRALS ? 1 : 2)];
		double t;
		int n;
		m_pData = new GArffData(nPoints);
		if(eType == SWISS_ROLL)
		{
			// Load the image mask (if necessary)
			GImage imageMask;
			if(bMask)
			{
				if(!imageMask.LoadPNGFile("mask.png"))
					GAssert(false, "failed to load mask");
			}

			for(n = 0; n < nPoints; n++)
			{
				t = ((double)n * 8) / nPoints;
				while(true)
				{
					double* pVector = new double[3];
					pVector[0] = (t + 2) * sin(t) + 14;
					pVector[1] = GBits::GetRandomDouble() * 12 - 6;
					pVector[2] = (t + 2) * cos(t);
					m_pData->AddVector(pVector);
					if(bComputeIdeal)
					{
						m_pIdealResults[2 * n] = pVector[1];
						m_pIdealResults[2 * n + 1] = LengthOfSwissRoll(t + 2);/* - LengthOfSwissRoll(2);*/
					}
					if(bMask)
					{
						int x = (int)(n * imageMask.GetWidth() / nPoints);
						int y = (int)((pVector[1] + 6) * imageMask.GetHeight() / 12);
						GColor c = imageMask.SafeGetPixel(x, y);
						if(gGreen(c) < 128)
							break;
					}
					else
						break;
				}
			}
		}
		else if(eType == S_CURVE)
		{
			for(n = 0; n < nPoints; n++)
			{
				t = ((double)n * 2.2 * PI - .1 * PI) / nPoints;
				double* pVector = new double[3];
				pVector[0] = 1.0 - sin(t);
				pVector[1] = t;
				pVector[2] = GBits::GetRandomDouble() * 2;
				m_pData->AddVector(pVector);
				if(bComputeIdeal)
				{
					m_pIdealResults[2 * n] = pVector[2];
					m_pIdealResults[2 * n + 1] = (n > 0 ? GMath::Integrate(LengthOfSineFunc, 0, t, n + 30) : 0);
				}
			}
		}
		else if(eType == SPIRALS)
		{
			double dHeight = 3;
			double dWraps = 1.5;
			double dSpiralLength = sqrt((dWraps * 2.0 * PI) * (dWraps * 2.0 * PI) + dHeight * dHeight);
			double dTotalLength = 2.0 * (dSpiralLength + 1); // radius = 1
			double d;
			for(n = 0; n < nPoints; n++)
			{
				t = ((double)n * dTotalLength) / nPoints;
				double* pVector = new double[3];
				if(t < dSpiralLength)
				{
					d = (dSpiralLength - t) * dWraps * 2 * PI / dSpiralLength; // d = radians
					pVector[0] = -cos(d);
					pVector[1] = dHeight * t / dSpiralLength;
					pVector[2] = -sin(d);
				}
				else if(t - 2.0 - dSpiralLength >= 0)
				{
					d = (t - 2.0 - dSpiralLength) * dWraps * 2 * PI / dSpiralLength; // d = radians
					pVector[0] = cos(d);
					pVector[1] = dHeight * (dSpiralLength - (t - 2.0 - dSpiralLength)) / dSpiralLength;
					pVector[2] = sin(d);
				}
				else
				{
					d = (t - dSpiralLength) / 2.0; // 2 = diameter
					pVector[0] = 2.0 * d - 1.0;
					pVector[1] = dHeight;
					pVector[2] = 0;
				}
				m_pData->AddVector(pVector);
				if(bComputeIdeal)
					m_pIdealResults[n] = dTotalLength * n / nPoints;
			}
		}

		// Allocate the sculpter
		m_pSculpter = new GManifoldSculpting(m_pData->GetSize(), m_pRelation->GetInputCount(), nNeighbors);
		m_pSculpter->SetData(m_pRelation, m_pData);
		m_pSculpter->SetSquishingRate(dSquishingRate);
		m_pSculpter->SetSmoothingAdvantage(10);

		// Init the sculpter
		m_pSculpter->SquishBegin(/*nTargetDimensions*/(eType == SPIRALS ? 1 : 2));

		// Set the supervised points
		if(nSupervisedPoints > 0)
		{
			int i;
			for(i = 0; i < nSupervisedPoints; i++)
			{
				int nPoint = rand() % nPoints;
				m_pSculpter->SetVector(nPoint, pTrainedModel->GetSculpter()->GetVector(nPoint), false);
			}
		}
	}

	virtual ~SwissRollModel()
	{
	}

	void PreProcess(bool bLLE)
	{
/*		if(bLLE)
		{
			// Compute data range
			double dTmp, dInputRangeX, dInputRangeY, dLLERangeX, dLLERangeY;
			m_pData->GetMinAndRange(0, &dTmp, &dInputRangeX);
			m_pData->GetMinAndRange(1, &dTmp, &dInputRangeY);

			printf("Pre-processing with LLE...\n");
			GArffData* pPreprocessedData = NULL;
			int nLen;
			char* pFile = GFile::LoadFileToBuffer("lledata.arff", &nLen);
			if(pFile)
			{
				// Load the LLE data from a file (since my LLE implementation is so slow)
				Holder<char*> hFile(pFile);
				GArffRelation* pTmpRelation = GArffRelation::ParseFile(&pPreprocessedData, pFile, nLen);
				Holder<GArffRelation*> hTmpRelation(pTmpRelation);
				GAssert(pTmpRelation && pPreprocessedData, "failed to parse lle file");
			}
			else
			{
				// Compute the LLE transformation of the data
				pPreprocessedData = GLLE::DoLLE(m_pRelation, m_pData, 14);
				m_pRelation->SaveArffFile(pPreprocessedData, "lledata.arff");
			}
			Holder<GArffData*> hPreprocessedData(pPreprocessedData);

			// Normalize the data
			pPreprocessedData->GetMinAndRange(0, &dTmp, &dLLERangeX);
			pPreprocessedData->GetMinAndRange(1, &dTmp, &dLLERangeY);
			pPreprocessedData->Normalize(0, 0, dLLERangeX, 0, dInputRangeX);
			pPreprocessedData->Normalize(1, 0, dLLERangeY, 0, dInputRangeY);

			// Set the new data
			m_pSculpter->SetData(m_pRelation, pPreprocessedData);
			printf("Done\n");
		}
		else
		{
			printf("Done\n");
			GArffData* pPreprocessedData = GPCA::DoPCA(m_pRelation, m_pData);
			Holder<GArffData*> hPreprocessedData(pPreprocessedData);
			m_pSculpter->SetData(m_pRelation, pPreprocessedData);
		}
*/
	}

	void DoSemiSupervisedThing()
	{
		// Make another swiss roll
		int nNeighbors = 24;
		GManifoldSculpting* pSculpter = new GManifoldSculpting(SWISS_ROLL_POINTS, 3, nNeighbors);
		pSculpter->SetSquishingRate(.99);
		pSculpter->SetSmoothingAdvantage(10);
		srand(0); // Make sure we always get consistent results
		double values[3];
		double t;
		int n;
		for(n = 0; n < SWISS_ROLL_POINTS; n++)
		{
			t = ((double)n * 8) / SWISS_ROLL_POINTS;
			values[0] = (t + 2) * sin(t) + 14;
			values[1] = ((double)GBits::GetRandomUint() / 0xffffffff) * 12 - 6;
			values[2] = (t + 2) * cos(t);
			pSculpter->SetVector(n, values, true);
		}

		// Init the sculpter
		pSculpter->SquishBegin(2);

		// Set some supervised points
		for(n = 0; n < SWISS_ROLL_POINTS; n++)
		{
			if(rand() % 20 == 0)
				pSculpter->SetVector(n, m_pSculpter->GetVector(n), false);
		}

		// Swap in the new sculpter
		delete(m_pSculpter);
		m_pSculpter = pSculpter;
	}
};

// virtual
double Compute2DErrorCritic::ComputeError(double* pVector)
{
	return m_pModel->Compute2DError(pVector[0], pVector[1], pVector[2], pVector[3], pVector[4]);
}

// virtual
double Compute1DErrorCritic::ComputeError(double* pVector)
{
	return m_pModel->Compute1DError(pVector[0], pVector[1]);
}


char* MakeEightDigitInt(int n, char* szBuf)
{
	sprintf(szBuf, "%d", n);
	int len = strlen(szBuf);
	int i;
	for(i = 7 - len; i >= 0; i--)
		szBuf[i] = '0';
	sprintf(szBuf + 8 - len, "%d", n);
	return szBuf;
}

class ImageModel : public ManifoldModel
{
protected:
	GImage* m_pImages;

public:
	ImageModel(int nSkip, int nImageCount, int nImageWidth, int nImageHeight, int nTargetDims, int nNeighbors, double dSquishingRate, const char* szFilenamePrefix, int nSupervisedPoints, ImageModel* pTrainedModel, bool bComputeIdeal) : ManifoldModel()
	{
		printf("Image Count=%d, wid=%d, hgt=%d, target dims=%d, neighbors=%d, squishing rate=%f, supervised points=%d\n", nImageCount, nImageWidth, nImageHeight, nTargetDims, nNeighbors, dSquishingRate, nSupervisedPoints);
		int nAttrs;
		m_pImages = new GImage[nImageCount];
		nAttrs = nImageWidth * nImageHeight;

		// Make the relation
		m_pRelation = new GArffRelation();
		int i, x, y;
		for(i = 0; i < nAttrs; i++)
			m_pRelation->AddAttribute(new GArffAttribute(true, 0, NULL));

		// Load the images into the ARFF data
		m_pData = new GArffData(nImageCount);
		const char* szAppPath = ControllerBase::GetAppPath();
		int nLen = strlen(szAppPath);
		GTEMPBUF(char, szFilename, nLen + 32);
		strcpy(szFilename, szAppPath);
		strcat(szFilename, szFilenamePrefix);
		nLen += strlen(szFilenamePrefix);
		double* pVector;
		int nGrayScaleValue;
		GColor col;
		int nSmoothingAdvantage = 10;
		nNeighbors = FACE_NEIGHBORS;
		char szTmp[9];
		for(i = 0; i < nImageCount; i++)
		{
			MakeEightDigitInt(i + 1 + nSkip, szTmp);
			strcpy(szFilename + nLen, szTmp);
			strcpy(szFilename + nLen + 8, ".png");
			if(!m_pImages[i].LoadPNGFile(szFilename))
				throw "Failed to load image";
			GAssert((int)m_pImages[i].GetWidth() == nImageWidth, "unexpected size");
			GAssert((int)m_pImages[i].GetHeight() == nImageHeight, "unexpected size");
			pVector = new double[nImageWidth * nImageHeight];
			m_pData->AddVector(pVector);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?