libsvm C++での菜鳥レベルの使用


今回はlibsvmを用いて二分類を行います.
データセットUCIのAdult:http://archive.ics.uci.edu/ml/datasets/Adult
ツール:libsvm
言語:C++
 
libsvm C++のブログをたくさん見て、糞と同じ人もいます.
この2人のブロガーに感謝します.
https://blog.csdn.net/lhanchao/article/details/53367532
https://blog.csdn.net/zilongreco/article/details/41390385
非常に多くの有用な情報を与えた.
 
私自身は文章が下手で、自分が意味をはっきり言っていないかもしれませんが、私は確かにみんなに分かち合いたいと思っています.
 
Libsvm構造体:
中にはsvm_が紹介されていますproblem、svm_Nodeなどの構造体は、とても大きな助けを与えてくれて、改めて感謝します.
C++のlibsvmを使ったコードを書くには、構造体を理解しなければなりません.
次はlibsvmソースコードの中の
struct svm_node
{
	int index;
	double value;
};

struct svm_problem
{
	int l;
	double *y;
	struct svm_node **x;
};

svm_Nodeは、フィーチャーのシーケンス番号と値を格納します.indexはシーケンス番号で、値はvalueです.
例を挙げると,2つの特徴1つの結果のデータであり,1つの特徴は1つのnodeに対応する.
svm_problemは特徴全体を格納する構造体である
int lはデータの数で、あなたが何個のデータを持っているかです.yは各データの分類結果である.xは2次元配列で、あなたのデータのすべての特徴を詰めています.
二次元配列のような図で言えば、この図の大きなXと大きなYはsvm_です.problemの中のxとy.
libsvm C++中使用 菜鸟级别_第1张图片
分類するのは数歩にほかならない.
1.データのロード
2.洗浄データは正規化などを含む
3.給餌訓練データ訓練
4.予測検証
洗浄コードはPythonで書いたもので、文章の後ろにあります.
 
準備:
libsvmでまずダウンロードしなければなりませんか?
ダウンロードして、直接それを開けて、中のsvmを見つけます.h、svm-train.c、svm.cpp(これは使わないようです).
 
他の小さなツールを使うなら、このいくつかのファイルを同じディレクトリにすればいいだけで、どうせファイルを導入するだけで、何も言うことはありません.
VSを使うなら、新しいプロジェクトを作ってsvm.h導入してsvm-train.cとsvm.cppが導入された.
これであなたのプロジェクトはこのようなディレクトリになります.私のプロジェクトの名前はlibsvmです.プレイ、遊びです.
案内してsvmを見つけたcppのmain.
彼のこのmainは、コンソールを使っています.私たちのこのバージョンはコードで直接実行されています.だから、私たちは彼のこのmainを使わないで、直接削除したり注釈したりしません.
libsvm C++中使用 菜鸟级别_第2张图片
そうだVSならpchを使わないほうがいい.h……
 
コード解析:
データのロードと洗浄のデータコードはPythonで書かれていますが、文章の後では省略します.
洗浄したデータをDataという2次元配列に入れました.
TrainingNumberはトレーニングデータ量、FeatureNumberは特徴数(分類結果を含む).
新しいストレージフィーチャーのx_を先にnewしましたスペース、そしてsvm_problemのポインタがそれを指しているので、もっと便利です.
x_Nodeのindexが-1に等しいと,1つのデータの特徴の入力が終了することを示す.
必ず-1をプラスすることを覚えています!
void FeedData(svm_problem *problem){
	if (param.gamma == 0) param.gamma = 0.5;

	problem->l = TrainingNumber;
	problem->y = new double[problem->l];

	svm_node *x_space = new svm_node[(FeatureNumber + 1)*problem->l];//to restore feature
	problem->x = new svm_node *[problem->l]; //every X points to one sample

	int cnt = 0;
	for (int i = 0;i < TrainingNumber;i++) {
		int before = cnt;
		for (int j = 0;j < FeatureNumber-1;j++) {
			x_space[cnt].index = j;
			x_space[cnt].value = Data[i][j];
			cnt++;
		}
		x_space[cnt].index = -1;
		cnt++;
		problem->x[i] = &x_space[before];
		problem->y[i] = Data[i][FeatureNumber - 1];
	}

}

 
書類全体を載せて、
コードは少し長くて、その中の肝心なのは私の上のデータをSVMに供給するだけで、train SVMは1つの関数を呼び出すだけでいいです.predictも同様に関数を呼び出すだけで、1行だけです.
#include 
#include 
#include 
#include 
#include 
#include 
#include "svm.h"
#include 
using namespace std;

const int maxn = 4e4 + 10;
const int FeatureNumber = 15;//Feature includes result, which is the last feature.
const int DataNumber = 100;//3e4 + 5;
const int TrainingNumber = 10;
svm_parameter param;

double Data[maxn][FeatureNumber];

double ToNum(string a) {
	double ans = 0;
	int pos = -1;
	for (int i = 0;i < a.length();i++) {
		if (a[i] == '.') {
			pos = i+1;
			continue;
		}
		ans = ans * 10 + (a[i] - '0');
	}
	if (pos == -1) return ans;
	else return ans/pow(10,a.length()-pos);
}
bool LoadData(string path) {
	ifstream FileIn;

	try { FileIn.open(path); }
	catch (exception e) { cout << "file cannot be opened or found." << endl; return false; }

	string line;
	bool f = 0;
	int cnt = 0;
	while (getline(FileIn, line)) {
		if (cnt > FeatureNumber) break;

		if (f == 0) { f = 1;continue; }

		vector  temp;

		int before = 0;
		for (int i = 0;i < line.length();i++) {
			if (line[i] == ',' || line[i] == '
') { string sub = line.substr(before, i - before); temp.push_back(ToNum(sub)); before = i + 1; } } temp.push_back(ToNum(line.substr(before, line.length() - before))); if (temp.size() != FeatureNumber) { cout << "data corrupted. Feature number doesn't match." << endl;exit(0); } for (int i = 0;i < temp.size();i++) Data[cnt][i]=temp[i]; cnt++; } cout << "data loading done.
total number of data is: " << cnt << endl << endl; } void ShowData() { for (int i = 0;i < TrainingNumber;i++) { for (int j = 0;j < FeatureNumber;j++) cout << setw(5) << Data[i][j] << " "; cout << endl; } } void FeedData(svm_problem *problem){ if (param.gamma == 0) param.gamma = 0.5; problem->l = TrainingNumber; problem->y = new double[problem->l]; svm_node *x_space = new svm_node[(FeatureNumber + 1)*problem->l];//to restore feature problem->x = new svm_node *[problem->l]; //every X points to one sample int cnt = 0; for (int i = 0;i < TrainingNumber;i++) { int before = cnt; for (int j = 0;j < FeatureNumber-1;j++) { x_space[cnt].index = j; x_space[cnt].value = Data[i][j]; cnt++; } x_space[cnt].index = -1; cnt++; problem->x[i] = &x_space[before]; problem->y[i] = Data[i][FeatureNumber - 1]; } } void ShowFeedData(svm_problem *problem) { for (int i = 0;i < TrainingNumber;i++) { for (int j = 0;j < FeatureNumber;j++) { if (problem->x[i][j].index == -1) break; cout <x[i][j].value<y[i]; } cout << endl; } } int Predict(double *f,svm_model *m) { svm_node feature[FeatureNumber-1]; for (int i = 0;i < FeatureNumber-1;i++) { feature[i].index = i; feature[i].value = f[i]; } return svm_predict(m, feature); } void init_param() { param.svm_type = C_SVC; param.kernel_type = RBF; param.degree = 3; param.gamma = 0.0001; param.coef0 = 0; param.nu = 0.5; param.cache_size = 100; param.C = 10; param.eps = 1e-5; param.shrinking = 1; param.probability = 0; param.nr_weight = 0; param.weight_label = NULL; param.weight = NULL; } int main() { string path("C:\\Users\\Lenovo\\Desktop\\adult_new.csv"); LoadData(path); cout << "Data is" << endl; //ShowData(); cout << endl; init_param(); svm_problem prob; FeedData(&prob); //cout << "Fed Data is:" << endl; //ShowFeedData(&prob); svm_model *model = svm_train(&prob, &param); double feature[] = { 5.6,0.4,0.1473,0.0,0.0,0.1,1.0,0.1,0.0,0.0,0.0,0.0,4.0,0.0 };//1 cout << Predict(feature, model) << endl; cout << "this is it! it worked." << endl; delete[] prob.x; delete[] prob.y; exit(0); }

 
 
添付:
このデータセットは文字型で、C++は相対的に下位の言語なので、pythonでデータ洗浄を行い、データプログラミングがSVMのデータに直接与えることができます.
Pythonコードを置いてください.

class Modifier:
	def __init__(self):
		self.Data=[]
		self.RawData=[]
		self.NUMOFDATA=0
		self.NUMOFFEATURE=0
		self.GetClass={}
		self.SecondFeatureMin = 12285
		self.SecondFeatureMax = 1484705
		self.Second = self.SecondFeatureMax - self.SecondFeatureMin

	def LoadData(self, PATH):
		with open(PATH, 'r') as f:
			for line in f:
				self.RawData.append([thing.strip() for thing in line.split(',')])
		self.RawData = self.RawData[:-1]
		self.NUMOFDATA = len(self.RawData)

	def ShowRawData(self):
		for item in self.RawData:
			print(item)

	def WashData(self):
		attribute = len(self.RawData[0])
		# print("attribute: {}".format(attribute))

		index = 0
		while index < attribute:
			# print('index: {}'.format(index))
			cnt = 0
			temp = [i[index] for i in self.RawData]

			for item in temp:
				if item not in self.GetClass:
					self.GetClass[item] = cnt
					cnt += 1
			index += 1
		self.NUMOFFEATURE = index

		# print("feature number is {}.".format(self.NUMOFFEATURE))
		for line in self.RawData:
			t = []
			for j, f in enumerate(line):
				if j == 0:
					t.append(float(f) / 10)
				elif j == 2:
					t.append(round(float(f) / self.Second, 4))
				elif j == 10 or j == 11:
					t.append(float(f) / 2000)
				elif j == 12:
					t.append(float(f) / 10)
				elif j==14:
					t.append(self.GetClass[f] )
				else:
					t.append(self.GetClass[f]/10)
			self.Data.append(t)

		# print("data length is {}".format(len(self.Data[0])))

	def ShowData(self):
		for item in self.Data:
			print(item)
	def WriteData(self,PATH):
		with open(PATH,'w') as f:
			for item in self.Data:
				f.write(','.join([str(i) for i in item])+'
') if __name__=='__main__': m=Modifier() m.LoadData(r"C:\Users\Lenovo\Desktop\adult.csv") #m.ShowRawData() m.WashData() #m.ShowData() m.WriteData(r"C:\Users\Lenovo\Desktop\adult_new.csv")