SHOGUN  4.1.0
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
DeveloperTutorial.mainpage
浏览该文件的文档.
1 /*!
2 \page developer_tutorial Libshogun使用指南和开发者指南
3 
4 Shogun分成两个部分:libshogun,它包含了已实现的所有机器学习算法;libshogunui,
5 它是一个接口库,提供各种静态和模块化接口,静态接口包括python、octave、matlab和r,
6 模块化接口包括python_modular、octave_modular和r_modular(各种接口可以在src/目录
7 下找到相应的子目录)。关于如何安装shogun请看src/INSTALL。
8 
9 如果要想扩展shogun,最好方法就是开始使用它提供的库。通过查看examples/libshogun
10 的例子你可以很容易学习使用它。
11 
12 最简单的基于libshogun的程序如下所示:
13 
14 \verbinclude minimal.cpp
15 
16 它可以通过g++ -lshogun minimal.cpp -o minimal来编译,很显然它什么事情都没有做
17 (除了在内部初始化了一组全局变量并销毁它们)。
18 
19 如果想重定向shogun的输出函数SG_DEBUG()、SG_INFO()、SG_WARN()、SG_ERROR()、SG_PRINT()
20 等,你需要像下面这样把相应参数传给init_shogun()
21 
22 \verbatim
23 void print_message(FILE* target, const char* str)
24 {
25  fprintf(target, "%s", str);
26 }
27 
28 void print_warning(FILE* target, const char* str)
29 {
30  fprintf(target, "%s", str);
31 }
32 
33 void print_error(FILE* target, const char* str)
34 {
35  fprintf(target, "%s", str);
36 }
37 
38 init_shogun(&print_message, &print_warning,
39  &print_error);
40 \endverbatim
41 
42 如果要使用某些特性,你需要包含相应的头文件。例如,在下面的例子中我们创建了
43 一些feature和一个高斯核函数:
44 
45 \verbinclude minimal_svm.cpp
46 
47 你很可能感到奇怪,为什么这个例子不会有内存泄漏。首先,向指向数组的指针申请内存
48 后新建的shogun对象将使用这些内存,并会在shogun对象销毁的同时释放这此内存。每一个
49 新建的shogun对象在内部都有一个引用计数器。每当一个shogun对象被返回或者作为参数
50 传给某个函数时,它的引用计数就会增加,比如在上面的例子中
51 
52 \verbatim
53 CLibSVM* svm = new CLibSVM(10, kernel, labels);
54 \endverbatim
55 
56 kernel和labels的引用计数将会增加。析构对象的时候引用计数就会减少并且在引用计数
57 <=0时释放所占用的内存。
58 
59 如果你有全局句柄指向某些对象,这些对象你在后面还要使用,那么你要保证那些对象不会
60 被销毁。在上面的例子中,如果在调用SG_UNREF(svm)后再访问labels会造成段错误,因为在
61 调用SVM的析构函数时Label对象也被销毁了。你可以通过调用SG_UNREF(obj)来保证obj指向的
62 对象不被销毁。相反,调用SG_UNREF(obj)可以使obj的引用计数减一,并且在引用计数<= 0
63 时销毁obj指向的对象并设置obj=NULL。
64 
65 
66 一般地,所有的shogun的C++对象都以C为前缀,例如CSVM,它是继承于CSGObject。因为所有
67 基类的成员变量都要在创建对象时被初始化,所以创建对象时会调用基类的构造函数,如CSVM
68 调用CKernelMachine,CKernelMachine调用CClassifier,最后CClassifier调用CSGObject。
69 
70 如果你想实现一个自己的SVM(名为MySVM),你可以在MySVM的构造函数中这样做
71 
72 \verbatim
73 class MySVM : public CSVM
74 {
75  MySVM( ) : CSVM()
76  {
77 
78  }
79 
80  virtual ~MySVM()
81  {
82 
83  }
84 };
85 \endverbatim
86 
87 同时要保证你的析构函数是\b 虚函数。
88 
89 现在我们开始定义一个自己的核函数,一个类线性的核函数,它定义在double精度的浮点向量上。
90 定义如下:
91 
92 \f$k({\bf x}, {\bf x'}) = \sum_{i=1}^D x_i \cdot x'_{D-i+1}\f$
93 
94 其中D是数据的维数。
95 要实现这个核函数需要新建一个类CReverseLinearKernel,该类继承于CSimpleKernel<float64_t>
96 (如果输入是字符串,基类应该是CStringKernel,如果是稀疏feature向量,基类应该是CSparseKernel)
97 
98 实质上我们只需要用自己的实现来重载函数CKernel::compute()。其它都使用缺省的就可以了。
99 compute()的实现可以像这样
100 
101 
102 \verbatim
103 virtual float64_t compute(int32_t idx_a, int32_t idx_b)
104 {
105  int32_t alen, blen;
106  bool afree, bfree;
107 
108  float64_t* avec=
109  ((CSimpleFeatures<float64_t>*) lhs)->get_feature_vector(idx_a, alen, afree);
110  float64_t* bvec=
111  ((CSimpleFeatures<float64_t>*) rhs)->get_feature_vector(idx_b, blen, bfree);
112 
113  ASSERT(alen==blen);
114 
115  float64_t result=0;
116  for (int32_t i=0; i<alen; i++)
117  result+=avec[i]*bvec[alen-i-1];
118 
119  ((CSimpleFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a, afree);
120  ((CSimpleFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b, bfree);
121 
122  return result;
123 }
124 \endverbatim
125 
126 对于两个索引idx_a和idx_b,我们可以得到它们相应的feature向量,然后使用它们进行计算
127 (中间的for循环),最后释放这两个feature向量。需要注意的是在大多数情况下,获取feature向量
128 实际上就是一个访问内存操作(free_feature_vector一般是一个空操作)。然而,当preprocessor
129 对象被捆绑在某个feature对象时,feature对象会做一些预处理。
130 
131 一个完整的,可以工作的例子如下所示
132 
133 \verbinclude revlin_kernel.cpp
134 
135 你可以看到,还有其它一部分函数用于返回对象名,对象id,以及可以加载或保存核函数初始化
136 数据。如果你新建了一个SVM(从CSVM或CLinearClassifier继承而来)或者新建了一些feature对象
137 (从CFeatures,CSimpleFeatures,CStringFeatures,CSparseFeatures继承而来),这些函数
138 依然可以使用。对于SVM,你只需要重载CSVM::train(),参数设置如epsilon,C以及SVM评价函数
139 可以使用基类CSVM中的。
140 
141 如果你想整合你的类实现到shogun的模块化接口中,你所需要做的就是将该类放在一个头文件中并
142 在相应的.i文件中包含这个头文件(上面实现了一个Kernel类,所以相应的.i文件是
143 src/modular/Kernel.i)。你可以很容易找到一个类似的对象然后像它那样修改其中的三行:
144 首先是修改%{ %}语句块(这个会被swig忽略,swig用于产生python/octave的模块化接口)
145 
146 \verbatim
147 %{
148 #include <shogun/kernel/ReverseLinearKernel.h>
149 %}
150 \endverbatim
151 
152 然后去掉类名的C前缀(如果有的话)
153 
154 \verbatim
155 %rename(ReverseLinearKernel) CReverseLinearKernel;
156 \endverbatim
157 
158 最后告诉swig封装所在包包含在头文件中的函数
159 
160 \verbatim
161 %include <shogun/kernel/ReverseLinearKernel.h>
162 \endverbatim
163 
164 如果你发现自己设计的对象工作良好,而且符合shogun约定的代码规范,我们很乐意将它整合到shogun中。
165 代码规范的细节可见于 \subpage devel(其中包括格式、宏、类型、函数、命名等方面的约定)。请注意,
166 如果你修改了某些API那将破坏ABI兼容性,那样你需要增加libshogun soname(见\subpage soname)的主号。
167 
168 */

SHOGUN 机器学习工具包 - 项目文档