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

📄 kmeansdlg.cpp

📁 knn分类模式识别可用于文本挖掘和其他的识别分类,vc代码,
💻 CPP
字号:
// KMEANSDlg.cpp : implementation file
//

#include "stdafx.h"
#include "KMEANS.h"
#include "KMEANSDlg.h"

#include <math.h>
const int RawOfOutput = 25;
//const int NumOfTrain = 170;//对测试集
const int NumOfTrain = 514;//对训练集

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

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

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

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

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

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CKMEANSDlg dialog

CKMEANSDlg::CKMEANSDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CKMEANSDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CKMEANSDlg)
	m_result = _T("");
	m_showres = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CKMEANSDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CKMEANSDlg)
	DDX_Text(pDX, IDC_RecResult, m_result);
	DDX_Text(pDX, IDC_ShowRec, m_showres);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CKMEANSDlg, CDialog)
	//{{AFX_MSG_MAP(CKMEANSDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDKMeans, OnKMeans)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CKMEANSDlg message handlers

BOOL CKMEANSDlg::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
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CKMEANSDlg::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 CKMEANSDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (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();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CKMEANSDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////         KMEANS 方法聚类        ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//样本结构
struct Sample
{
	int category;
	int Recresult;
	double feature[10];
}train[NumOfTrain],PCentroid,NCentroid;
 
//////////////////////////////////////////////////////////////////////
//从文本行到向量的转换
Sample line2vector(CString line)
{
	int t,k;
	Sample tem;
	line.TrimLeft();
	//line.TrimRight();
	t = line.Find(' ');
	tem.category = atoi(line.Left(t));
	line = line.Mid(t);
	for(int i=1;i<10;i++)
	{
		line.TrimLeft();
		//line.TrimRight();
		t = line.Find(':') +1;
		k = line.Find(' ');
		tem.feature[i] = double(atoi(line.Mid(t,k - t)));
		line = line.Mid(k + 1);
	}
	return tem;
}

//////////////////////////////////////////////////////////////////////
//读取训练数据,存储为Sample结构
bool ReadTrainData()
{
	FILE *Tdata;
	Tdata = fopen("data\\train.txt","rt");//对训练集
    //Tdata = fopen("data\\test.txt","rt");//对测试集
	if(Tdata == NULL)
	{
		AfxMessageBox("File open Failed!");
	}
	CStdioFile TrainFile(Tdata);
	CString line;
	int nvector = 0;
	while(TrainFile.ReadString(line))
	{
	 	train[nvector] = line2vector(line);
		nvector++;
	}
	TrainFile.Close();
	return true;
}

//////////////////////////////////////////////////////////////////////
//取两向量的欧氏距离
double Distance(const Sample &s1,const Sample &s2)
{
	double sum = 0;
	double Odistance = 0;
    for(int i=1;i<10;i++)
	{
		sum += pow(s1.feature[i] - s2.feature[i],2);
	}
	return Odistance = sqrt(sum);
}


//////////////////////////////////////////////////////////////////////
//更新质心
void UpdateCentroid()
{
	double NSum[10],PSum[10];
	int i;
	int NNum = 0;
	int PNum = 0;
	for(i=1;i<10;i++)
	{
		NSum[i] = 0;
		PSum[i] = 0;
	}
 	for(i=0;i<NumOfTrain;i++)
	{
		if(train[i].Recresult == -1)
		{
			NNum++;
			for(int j=1;j<10;j++)
			{
				NSum[j] += train[i].feature[j];
			}
		}
		if(train[i].Recresult == 1)
		{
			PNum++;
            for(int j=1;j<10;j++)
			{
				PSum[j] += train[i].feature[j];
			}
		}
	}
	for(i=1;i<10;i++)
	{
		NCentroid.feature[i] = NSum[i]/NNum;
		PCentroid.feature[i] = PSum[i]/PNum;
	}
}

//////////////////////////////////////////////////////////////////////
//更新各样本识别结果

int UpdateRec(Sample Sam[])
{
	int num = 0;
	int temp;
	for(int i=0;i<NumOfTrain;i++)
	{
		temp = Sam[i].Recresult;

		Sam[i].Recresult = 
			(Distance(train[i],NCentroid) <= Distance(train[i],PCentroid))? -1:1;

		if(temp != Sam[i].Recresult)
		{
			num++;
		}
	}
	return num;
}

//////////////////////////////////////////////////////////////////////
//output
void CKMEANSDlg::output()
{
	UpdateData(true);
	int RightRec = 0;
	int WrongRec = 0;
    double Ratio;
	int Sum = 0;
	for(int i=1;i<=NumOfTrain;i++)
	{
		if(train[i-1].Recresult == train[i-1].category)//聚类正确
		{
			RightRec++;
			Sum++;
            if(i%RawOfOutput != 0 && train[i-1].Recresult == -1)
			{
				m_showres += "☆" ;
			}
			else if(i%RawOfOutput == 0 && train[i-1].Recresult == -1)
			{
				m_showres += "☆" ;
				m_showres += "\r\n";
			}
			else if(i%RawOfOutput != 0 && train[i-1].Recresult == 1)
			{
				m_showres += "○" ;
			}
            else if(i%RawOfOutput == 0 && train[i-1].Recresult == 1)
			{
				m_showres += "○" ;
				m_showres += "\r\n";
			}
		}
		else if(train[i-1].Recresult != train[i-1].category)//聚类错误
		{
			WrongRec++;
			Sum++;
			if(i%RawOfOutput != 0 && train[i-1].Recresult == -1)
			{
				m_showres += "★" ;
			}
			else if(i%RawOfOutput == 0 && train[i-1].Recresult == -1)
			{
				m_showres += "★" ;
				m_showres += "\r\n";
			}
			else if(i%RawOfOutput != 0 && train[i-1].Recresult == 1)
			{
				m_showres += "●" ;
			}
            else if(i%RawOfOutput == 0 && train[i-1].Recresult == 1)
			{
				m_showres += "●" ;
				m_showres += "\r\n";
			}
		}
	}
	Ratio = 100*(double)RightRec/Sum;
	m_result.Format("聚类正确率%5.1f%,\r\n正确分类数%5d,\r\n错误分类数%4d",Ratio,RightRec,WrongRec);
	UpdateData(false);
}


//////////////////////////////////////////////////////////////////////
//主函数
void CKMEANSDlg::OnKMeans() 
{
	while(!ReadTrainData())
	{
		MessageBox("TrainFile Read Failed!");
	}
	
	//初始化,设第一个样本为第一类中心点,与它的距离最远的样本为第二类中心点
	NCentroid = train[0];
	int PNumIni = 1;
	double Max = Distance(train[0],train[1]);
	for(int i=2;i<NumOfTrain;i++)
	{
		if(Distance(train[0],train[i]) > Max)
		{
			Max = Distance(train[0],train[i]);
            PNumIni = i;
		}
	}
    PCentroid = train[PNumIni];
	for(i=0;i<NumOfTrain;i++)
	{
		train[i].Recresult = 
			(Distance(train[i],NCentroid) <= Distance(train[i],PCentroid)) ? 
			     NCentroid.category : PCentroid.category;
	}

 	//循环至各样本的分类结果不再变化
	UpdateCentroid();
	int k = 0;
	while(UpdateRec(train) > 0)
	{
		UpdateCentroid();
		k++;
	}

	//结果输出
	output();
	CString msg;
	msg.Format("循环次数%d",k);
    MessageBox(msg);
}

⌨️ 快捷键说明

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