⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multilayerperceptrondlg.cpp

📁 多层神经网络范例 http://www.codeproject.com/cpp/MLP.asp?df=100&forumid=148477&exp=0&select=1141594#xx114159
💻 CPP
字号:
// MultiLayerPerceptronDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MultiLayerperceptron.h"
#include "MultiLayerPerceptronDlg.h"
#include ".\multilayerperceptrondlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define SAFE_DELETE(p) {if(p) {delete [] p; p = 0;}}
int totalIter = 0;
double* totalError = NULL;
HBRUSH brBlue = CreateSolidBrush(RGB(0,0,255));
HBRUSH brRed = CreateSolidBrush(RGB(255,0,0));
HPEN   penWhite = CreatePen(PS_SOLID, 1, RGB(255,255,255));
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

	// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

	// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CMultiLayerPerceptronDlg dialog



CMultiLayerPerceptronDlg::CMultiLayerPerceptronDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMultiLayerPerceptronDlg::IDD, pParent)
, m_dLearningRate(0.05)
, m_dMomentum(0.9)
, m_nIter(1000)
, m_dTargetError(0.03)
, m_bWritetoFile(FALSE)
, m_strErrorFile(_T("C:\\error.txt"))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_hidSize[0] = 10;
	m_hidSize[1] = 0;
	m_hidSize[2] = 0;
	for (int y = 0; y < 600; y++) 
	{
		for (int x = 0; x < 800; x++) 
		{
			m_fRedRatio[y][x] = -128;
		}
	}
}

void CMultiLayerPerceptronDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_HIDDEN1, m_hidSize[0]);
	DDX_Text(pDX, IDC_HIDDEN2, m_hidSize[1]);
	DDX_Text(pDX, IDC_HIDDEN3, m_hidSize[2]);
	DDX_Text(pDX, IDC_LR, m_dLearningRate);
	DDX_Text(pDX, IDC_MOMENTUM, m_dMomentum);
	DDX_Text(pDX, IDC_ITER, m_nIter);
	DDX_Control(pDX, IDC_COLOR, m_cmbColor);
	DDX_Text(pDX, IDC_TARGET_ERROR, m_dTargetError);
	DDX_Check(pDX, IDC_WRITETOFILE, m_bWritetoFile);
	DDX_Text(pDX, IDC_EDIT1, m_strErrorFile);
}

BEGIN_MESSAGE_MAP(CMultiLayerPerceptronDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_INIT, OnBnClickedInit)
	ON_BN_CLICKED(IDC_LEARN, OnBnClickedLearn)
	ON_WM_LBUTTONDOWN()
	ON_BN_CLICKED(IDC_CLEAR, OnBnClickedClear)
	ON_BN_CLICKED(IDC_SHOW_ERROR, OnBnClickedShowError)
	ON_BN_CLICKED(IDC_LOAD_WEIGHTS, OnBnClickedLoadWeights)
	ON_BN_CLICKED(IDC_LOAD_WEIGHTS2, SaveWeights)
	ON_BN_CLICKED(IDC_WRITETOFILE, OnBnClickedWritetofile)
END_MESSAGE_MAP()


// CMultiLayerPerceptronDlg message handlers

BOOL CMultiLayerPerceptronDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	m_ErrorDlg = new CErrorDlg(this);
	m_ErrorDlg->Create(IDD_ERROR);
	m_cmbColor.SetCurSel(0);

	RECT rc;
	GetDlgItem(IDC_SAMPLES)->GetClientRect(&rc);
	double W = rc.right - rc.left;
	double H = rc.bottom - rc.top;

	//POINT blues[] = {{0,0},{W,H}};
	POINT blues[] = {{W/2,2*H/3},{W/2,H/3},{W/3,H/2},{2*W/3,H/2},{5*W/12,7*H/12},{7*W/12,7*H/12},{5*W/12,5*H/12},{7*W/12,5*H/12}};
	for (int i = 0; i < 8; i++) 
	{
		m_BluePts.Add(blues[i]);
	}
	//POINT reds[] = {{0,H},{W,0}};
	//POINT reds[] = {{5*W/12,7*H/12},{7*W/12,7*H/12},{5*W/12,5*H/12},{7*W/12,5*H/12}};
	POINT reds[] = {{11*W/24,13*H/24},{13*W/24,13*H/24},{11*W/24,11*H/24},{13*W/24,11*H/24}};
	m_RedPts.Add(reds[0]);m_RedPts.Add(reds[1]);m_RedPts.Add(reds[2]);m_RedPts.Add(reds[3]);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMultiLayerPerceptronDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMultiLayerPerceptronDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
		int i;
		RECT rc;
		CDC* pDC = GetDlgItem(IDC_SAMPLES)->GetDC();
		pDC->SetBkMode(TRANSPARENT);

		//Classified regions
		for (int y = 0; y < 600; y++) 
		{
			for (int x = 0; x < 800; x++) 
			{
				if(m_fRedRatio[y][x] == -128)
					continue;
				int val = 255 - m_fRedRatio[y][x]*255;
				if(m_fRedRatio[y][x] > 0)
				{
					SetPixel(pDC->m_hDC, x, y, RGB(255,val,val));
				}
				else //if(m_fRedRatio[y][x] < 0)
				{
					val = -(-255 - m_fRedRatio[y][x]*255);
					SetPixel(pDC->m_hDC, x, y, RGB(val,val,255));
				}
			}
		}
		//Sample inputs from user
		pDC->SelectObject(penWhite);
		for (i = 0; i < m_RedPts.GetCount(); i++) 
		{
			RECT rc = {m_RedPts[i].x-4, m_RedPts[i].y-4, m_RedPts[i].x+4, m_RedPts[i].y+4};
			pDC->SelectObject(brRed);			
			//FillRect(pDC->m_hDC, &rc, brRed);
			pDC->Rectangle(&rc);
		}
		for (i = 0; i < m_BluePts.GetCount(); i++) 
		{
			RECT rc = {m_BluePts[i].x-4, m_BluePts[i].y-4, m_BluePts[i].x+4, m_BluePts[i].y+4};
			pDC->SelectObject(brBlue);
			//FillRect(pDC->m_hDC, &rc, brBlue);
			pDC->Rectangle(&rc);
		}

	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMultiLayerPerceptronDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CMultiLayerPerceptronDlg::OnBnClickedInit()
{
	for (int y = 0; y < 600; y++) 
	{
		for (int x = 0; x < 800; x++) 
		{
			m_fRedRatio[y][x] = -128;
		}
	}
	Invalidate();
	totalIter = 0;
	m_ErrorDlg->m_errorGraph.SetData(0,0,0,0);
	m_ErrorDlg->m_errorGraph.UpdateGraph();
	initPerceptron();
	GetDlgItem(IDC_LEARN)->EnableWindow(true);
	GetDlgItem(IDC_LOAD_WEIGHTS)->EnableWindow(true);
	GetDlgItem(IDC_SHOW_ERROR)->EnableWindow(true);
	GetDlgItem(IDC_SAVE_WEIGHTS)->EnableWindow(true);
}

void CMultiLayerPerceptronDlg::initPerceptron()
{
	UpdateData();

	int nLayer,i,j,k;

	perceptron = new Perceptron(n_in,n_out); // 2 inputs / 1 output
	nLayer=0;
	for(i=0;i<3;i++)
	{
		if (m_hidSize[i]!=0)
		{
			CString s;
			s.Format(_T("H%d|"),i);
			perceptron->addLayer(m_hidSize[i],s);
			nLayer++;
		}
	}
	for(j=0;j<nLayer;j++)
		for(i=0;i<m_hidSize[j];i++) perceptron->biasConnect(j+1,i);
	perceptron->biasConnect(nLayer+1,0); // for the output

	if (nLayer==0)
	{
		// connect the inputs to the outputs
		perceptron->connect(0,0,1,0);
		perceptron->connect(0,1,1,0);  
	}
	else
	{
		// connect the inputs to the first hidden layer
		for(i=0;i<m_hidSize[0];i++) 
			for(j=0;j<n_in;j++)
                perceptron->connect(0,j,1,i);
		// Problem with third layer solved by Sebastien Baehni
		// connect the hidden layers together
		for(k=0;k<nLayer-1;k++) 
			for(i=0;i<m_hidSize[k];i++) 
				for(j=0;j<m_hidSize[k+1];j++)
					perceptron->connect(k+1,i,k+2,j);
		// connect the last hidden layer to the output
		for(i=0;i<m_hidSize[nLayer-1];i++) perceptron->connect(nLayer,i,nLayer+1,0);
	}
}

void CMultiLayerPerceptronDlg::learnPoints()
{
	UpdateData();
	setSamples();
	// perceptron.printSamples();
	Neuron::learningRate = m_dLearningRate;

	SAFE_DELETE(totalError);
	int scale = 1;
	while ((m_nIter/scale) > 10000)
	{
		scale++;
	}
	//double* tmpError = new double[totalIter];
	//memcpy( tmpError, totalError, (totalIter-m_nIter)*sizeof(double) );
	totalError = new double[m_nIter/scale];
	UpdateData();
	FILE* fp = _wfopen(m_strErrorFile, _T("wt"));
	double err = 0;
	int i = 0;
	for(i = 0;i < m_nIter; i++)
	{
		perceptron->learn(1);
		if (i%scale==0)
		{
			SetDlgItemInt(IDC_COUNTER, i);
			totalError[i/scale] = perceptron->currentError();
			if(m_bWritetoFile)
				fprintf(fp,"%f\n",totalError[i/scale]);
			if(perceptron->currentError() < m_dTargetError)
				break;
		}
		//err = perceptron->currentError();
		//tmpError[i+totalIter-m_nIter] = err;
	}	
	//m_ErrorDlg->m_errorGraph.SetData(0,tmpError,totalIter,false);
	m_ErrorDlg->m_errorGraph.SetData(0,totalError,i/scale,false);
	//m_ErrorDlg->ShowWindow(SW_NORMAL);
	m_ErrorDlg->m_errorGraph.UpdateGraph();
	fclose(fp);
	//memcpy(totalError, tmpError, totalIter*sizeof(double));
	//delete [] tmpError;
	totalIter += i;
	SetDlgItemInt(IDC_TOTAL_ITER, totalIter);
}
void CMultiLayerPerceptronDlg::OnBnClickedLearn()
{
	learnPoints();
	UpdateDisplay();
}

void CMultiLayerPerceptronDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	UpdateData();
	ClientToScreen(&point);
	GetDlgItem(IDC_SAMPLES)->ScreenToClient(&point);
	RECT clientrc;
	GetDlgItem(IDC_SAMPLES)->GetClientRect(&clientrc);
	if(!PtInRect(&clientrc, point))
		return;
	RECT rc = {point.x-4, point.y-4, point.x+4, point.y+4};
	CDC* pDC = GetDlgItem(IDC_SAMPLES)->GetDC();
	if(m_cmbColor.GetCurSel() == 0)
	{
		FillRect(pDC->m_hDC, &rc, brBlue);
		m_BluePts.Add(point);
	}
	else
	{
		FillRect(pDC->m_hDC, &rc, brRed);
		m_RedPts.Add(point);
	}
	CDialog::OnLButtonDown(nFlags, point);
}
void CMultiLayerPerceptronDlg::setSamples()
{
	Samples iS,oS;
	oS.nLenght = 1;
	oS.samples[0] = 1.0;
	iS.nLenght = 2;
	RECT rc;
	GetDlgItem(IDC_SAMPLES)->GetClientRect(&rc);
	double W = rc.right - rc.left;
	double H = rc.bottom - rc.top;
	for (int i = 0; i < m_RedPts.GetCount(); i++) 
	{
		iS.samples[0] = (double)m_RedPts[i].x/W;
		iS.samples[1] = (H - (double)m_RedPts[i].y)/H;
		perceptron->addSample(iS, oS);
	}

	oS.samples[0] = 0.0;
	for (int i = 0; i < m_BluePts.GetCount(); i++) 
	{
		iS.samples[0] = (double)m_BluePts[i].x/W;
		iS.samples[1] = (H - (double)m_BluePts[i].y)/H;
		perceptron->addSample(iS, oS);
	}
}

void CMultiLayerPerceptronDlg::UpdateDisplay()
{
	RECT rc;
	GetDlgItem(IDC_SAMPLES)->GetClientRect(&rc);
	double W = rc.right - rc.left;
	double H = rc.bottom - rc.top;
	Samples test = {{0.0,0.0},2};
	int x = 0, y = 0;
	CDC *pDc = GetDlgItem(IDC_SAMPLES)->GetDC();
	pDc->SetBkMode(TRANSPARENT);
	POINT point;
	double result;
	for (y = 0; y < H; y++) 
	{
		for (x = 0; x < W; x++)
		{
			test.samples[0] = (double)x/W;
			test.samples[1] = (double)y/H;
			double result = perceptron->recognize(test).samples[0];
			m_fRedRatio[(int)H-y][x] = (result-0.5)/0.5;//number between -1 and 1
			/*if(perceptron->recognize(test).samples[0] > 0.5)
			{
				m_fRedRatio[(int)H-y][x] = 1;
			}
			else
			{
				m_fRedRatio[(int)H-y][x] = 0;
			}*/
		}
	}
	InvalidateRect(&rc,false);
};
void CMultiLayerPerceptronDlg::OnBnClickedClear()
{
	m_RedPts.RemoveAll();
	m_BluePts.RemoveAll();
	for (int y = 0; y < 600; y++) 
	{
		for (int x = 0; x < 800; x++) 
		{
			m_fRedRatio[y][x] = -128;
		}
	}
	Invalidate();
}

void CMultiLayerPerceptronDlg::OnBnClickedShowError()
{
	m_ErrorDlg->ShowWindow(SW_NORMAL);
}

void CMultiLayerPerceptronDlg::OnBnClickedLoadWeights()
{
	perceptron->LoadNet(_T("C:\\OCRNet.net"));
}

void CMultiLayerPerceptronDlg::SaveWeights()
{
	perceptron->SaveNetwork(_T("C:\\OCRNet.net"));
}

void CMultiLayerPerceptronDlg::OnBnClickedWritetofile()
{
	UpdateData();
	GetDlgItem(IDC_EDIT1)->EnableWindow(m_bWritetoFile);
}

⌨️ 快捷键说明

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