├── COPYRIGHT-libsvm
├── FAQ.html
├── LICENSE-libMR.txt
├── LICENSE-libsvm-openset.txt
├── Makefile
├── Makefile.win
├── README
├── README-libsvm-openset
├── heart_scale
├── java
├── Makefile
├── libsvm.jar
├── libsvm
│ ├── svm.java
│ ├── svm.m4
│ ├── svm_model.java
│ ├── svm_node.java
│ ├── svm_parameter.java
│ ├── svm_print_interface.java
│ └── svm_problem.java
├── svm_predict.java
├── svm_scale.java
├── svm_toy.java
├── svm_train.java
└── test_applet.html
├── matlab
├── Makefile
├── README
├── libsvmread.c
├── libsvmwrite.c
├── make.m
├── svm_model_matlab.c
├── svm_model_matlab.h
├── svmpredict.c
└── svmtrain.c
├── python
├── Makefile
├── README
├── svm.py
└── svmutil.py
├── svm-analyze.c
├── svm-predict.cpp
├── svm-scale.c
├── svm-toy
├── gtk
│ ├── Makefile
│ ├── callbacks.cpp
│ ├── callbacks.h
│ ├── interface.c
│ ├── interface.h
│ ├── main.c
│ └── svm-toy.glade
├── qt
│ ├── Makefile
│ └── svm-toy.cpp
└── windows
│ └── svm-toy.cpp
├── svm-train.cpp
├── svm.cpp
├── svm.def
├── svm.h
└── tools
├── README
├── checkdata.py
├── easy.py
├── grid.py
└── subset.py
/COPYRIGHT-libsvm:
--------------------------------------------------------------------------------
1 | Copyright (c) 2000-2011 Chih-Chung Chang and Chih-Jen Lin
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in the
13 | documentation and/or other materials provided with the distribution.
14 |
15 | 3. Neither name of copyright holders nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
24 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/LICENSE-libMR.txt:
--------------------------------------------------------------------------------
1 | SOURCE CODE LICENSE AGREEMENT
2 | PREAMBLE
3 |
4 | This SOFTWARE implements concepts of statistical Meta-recognition for which Securics/Univ. of Colorado have a pending patent (CU TTO File CU2338C). Securics and University of Colorado, hereafter The Owners, have joint interest in the invention and the software. Securics currently holds the excusive license commercial to both the patent and the code. Securcs, hereafter the Licensor, is offering a non-exclusive right to use for non-commecial use.
5 |
6 |
7 | This license agreement allows you to use the source code for personal or non profit purposes. This includes any use that does not involve making money, and does not include uses like:
8 | • deploying the software for use by a for-profit organization
9 | • providing a service to a paying customer
10 | For-profit companies may not use this source code. If you work for a for-profit company, you may only use this software as an individual, for your personal use.
11 |
12 | This is a right to use license. It does not not include the right to redistribute copies. Non-profit users can only use the copies obtained from authroized sourcehs which include: securics.com, metarecognition.com or vast.uccs.edu.
13 |
14 | This license agreement also allows you to create derivative products for your own use, but does not permit re-distribute
15 | of modified code in any form. You may choose to destribute patch files, which can be applied to officially distributed
16 | code. Any the derivative products, must be distributed under the same conditions as specified in this agreement unless
17 | a separate commercial license is obtained from Securics Inc or its designates.
18 |
19 | As a condition of using this source code, you agree not to assert any patents or copyrights against the owners or any of
20 | the Owners’ licensees for use of derivative products. Any derivative products must include a copy of license and
21 | instructions for accessing the orignal source. You must also include attribution to the authors in any publication that
22 | results from the use of this code or data derived from the code. Any papers/research/report based on results that uses
23 | this software must cite:
24 |
25 | @article{Scheirer_2011_TPAMI,
26 | author = {Walter J. Scheirer and Anderson Rocha and Ross Michaels and Terrance E. Boult},
27 | title = {Meta-Recognition: The Theory and Practice of Recognition Score Analysis},
28 | journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI)},
29 | volume = {33},
30 | issue = {8},
31 | pages = {1689--1695},
32 | year = {2011}
33 | }
34 |
35 |
36 | Parts of this technology are subject to SBIR data rights and as described in DFARS 252.227-7018 (June 1995) SBIR Data Rights which apply to Contract Number: N00014-11-C-0243 and STTR N00014-07-M-0421 to Securics Inc, 1870 Austin Bluffs Parkway, Colorado Springs, CO 80918
37 |
38 | The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights in Noncommercial Technical Data and Computer Software-Small Business Innovative Research (SBIR) Program clause contained in the above identified contract. Expiration of SBIR Data Rights: Expires four years after completion of the above cited project work for this or any other follow-on SBIR contract, whichever is later.
39 |
40 | No restrictions on government use apply after the expiration date shown above. Any reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce the markings.
41 |
42 |
43 |
44 |
45 |
46 | This license includes other conditions that should be read carefully. This SOFWARE usage agreement (the "Agreement") applies to the libMR and is between YOU and the Licensor
47 |
48 | 1. DEFINITIONS
49 |
50 | "Software" means all or any portion of the human-readable source code files of the software programs including without limitation, associated flow charts, algorithms, comments and other written instructions and technical documentation, and all corrections, updates, and new versions incorporated into such programs.
51 |
52 | “Derivative Work” means a work based upon the Software, such as a revision, modification, translation, abridgement, condensation, expansion, collection, compilation, or any other form in which the Software may be recast, transformed, adapted, or distributed as a part of a larger work and which, if prepared without proper authorization would constitute a copyright infringement. If identifiable sections of that work are not derived from the Software, and can be reasonably considered independent and separate works in themselves, then they are not considered Derivative Work.
53 |
54 | "Personal Use" means use of Software and/or Derivative Work by an individual solely for his or her personal, private and non-commercial use. An individual's use in his or her capacity as an officer, employee, member, independent contractor or agent of a corporation, business or organization does not qualify as Personal Use.
55 |
56 | "You" or "Your" means an individual or a legal entity exercising rights under this License. For legal entities, "You" or "Your" includes any non-profit entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the beneficial ownership of such entity.
57 |
58 | 2. GRANT OF LICENSE:
59 |
60 | WHEREAS, the Licensor, desires to aid the academic and non-commercial research community and raise awareness of the PATENTED INVENTION and thereby agrees to grant a limited copyright license to the SOFTWARE for research and non-commercial purposes only, with the Owners retaining all ownership rights in the PATENTED INVENTION and the SOFTWARE;
61 |
62 | THEREFORE:
63 | The Licensor grants, and You accept, a personal, nonexclusive, nontransferable license:
64 |
65 | a) to use Software, at no charge, in accordance with the terms herein, solely for (i) Personal Use, or (ii) academic or non-commercial research, development and deployment; and
66 |
67 | b) to develop Derivative Works that may be used solely for (i) Personal Use or (ii) academic or non-commercial research, development and deployment; and
68 |
69 | c) to copy, distribute and sublicense Software and Derivative Works solely in accordance with the terms herein. Any Software or Derivative Works distributed shall be pursuant to a license agreement that contains all of the terms herein; and shall contain prominent notices stating how the Software, Derivative Works, or documentation was changed, the author and date of any such change and require acknowledgement of the orginal software/publicaitons by any users of the Derivative Works.
70 |
71 | d) You acknowledge that the Software is a valuable, proprietary asset of The Owners. You shall not market or sell the Software or Derivative Works.
72 |
73 | 3. LICENSE EXCLUSIONS
74 |
75 | a) EXCEPT AS EXPRESSLY PROVIDED HEREIN, YOU SHALL MAKE NO OTHER USE OF THE SOFTWARE.
76 |
77 | b) You must obtain permission from The Licensor before receiving payment for distribution of or services using the Software or Derivative Works.
78 |
79 | c) You shall not allege or enjoin infringement or misappropriation by The Licensor in any Derivative Works, or by any third party obtaining Derivative Works, prepared by The Licensor and under license from The Licensor.
80 |
81 |
82 | 4. TITLE AND PROTECTION OF SOFTWARE
83 |
84 | a) The Owners retains all title, right and interest to the Software and the underlying patents.
85 |
86 | b) Except for the Software, You retain all title, right and interest to the Derivative Works, subject to the terms of this Agreement.
87 |
88 | 5. NO REPRESENTATIONS
89 |
90 | THE OWNERS DISCLAIMS ALL OTHER REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
91 |
92 |
93 | 6. ATTRIBUTION
94 |
95 | a) You agree to retain and reproduce in all copies of Software the copyright and other proprietary notices and disclaimers as they appear in the Software, and keep intact all notices in the Software that refer to this License.
96 |
97 | b) You agree to provide attribution to the authors of this Software in any article based on research performed using Software or Derivative Works or with any distribution of Software or Derivative works.
98 |
99 | 7. DEFAULT
100 |
101 | If YOU fail to perform any of its obligations under this Agreement, The Licensor, in addition to any other rights available to it under law or equity, may terminate this Agreement and the licenses granted hereunder by written notice to You. Unless otherwise provided in this Agreement, remedies shall be cumulative and there shall be no obligation to exercise a particular remedy.
102 |
103 | 8. TERMINATION
104 |
105 | a) In the event that this Agreement is terminated, any sublicenses granted or Derivative Works distributed by Licensee shall remain in full force and effect.
106 |
107 | b) Within thirty (30) days of termination, You shall return to The Licensor or certify in writing to The Licensor that all copies or partial copies of Software in Your possession or control have been destroyed. c) In addition to this section, the sections entitled "Title and Protection of Software "No Representations" and “Limitation of Liability" shall survive termination of this Agreement.
108 |
109 | 9. GENERAL
110 | a) No agency, partnership or employment is created by this Agreement.
111 |
112 | b) You may not use any of The Owners’ names, the terms in Meta-Recognition, or W-score in any advertising, public relations or media release without the prior written consent of the Owner.
113 |
114 | c) This Agreement shall be governed by the laws of the State of Colorado. Venue for any action or proceeding shall be Denver, Colorado. This Agreement constitutes the entire agreement between the parties and may only be modified by a written instrument signed by each parties authorized officers.
--------------------------------------------------------------------------------
/LICENSE-libsvm-openset.txt:
--------------------------------------------------------------------------------
1 | SOURCE CODE LICENSE AGREEMENT
2 | This SOFTWARE implements concepts of open-set recognition techniques mentioned in [1] [2] using LIBSVM (copy right specified in COPYRIGHT-libsvm file) and libMR (license information specified in LICENSE-libsvm file). The use of libsvm-openset library is subject to Copyright information of LIBSVM library and libMR license.
3 | All rights reserved.
4 |
5 |
6 |
7 |
8 |
9 | LIBSVM COPYRIGHT INFORMATION:
10 | Copyright (c) 2000-2011 Chih-Chung Chang and Chih-Jen Lin
11 | All rights reserved.
12 |
13 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
14 |
15 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
16 |
17 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 |
20 | 3. Neither name of copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software
21 | without specific prior written permission.
22 |
23 |
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 |
27 |
28 |
29 |
30 |
31 | LIBMR LICENSE INFORMATION:
32 | SOURCE CODE LICENSE AGREEMENT
33 | PREAMBLE
34 |
35 | This SOFTWARE implements concepts of statistical Meta-recognition for which Securics/Univ. of Colorado have a pending patent (CU TTO File CU2338C). Securics and University of Colorado, hereafter The Owners, have joint interest in the invention and the software. Securics currently holds the excusive license commercial to both the patent and the code. Securcs, hereafter the Licensor, is offering a non-exclusive right to use for non-commecial use.
36 |
37 | This license agreement allows you to use the source code for personal or non profit purposes. This includes any use that does not involve making money, and does not include uses like:
38 | • deploying the software for use by a for-profit organization
39 | • providing a service to a paying customer
40 | For-profit companies may not use this source code. If you work for a for-profit company, you may only use this software as an individual, for your personal use.
41 |
42 | This is a right to use license. It does not not include the right to redistribute copies. Non-profit users can only use the copies obtained from authroized sourcehs which include: securics.com, metarecognition.com or vast.uccs.edu.
43 |
44 | This license agreement also allows you to create derivative products for your own use, but does not permit re-distribute
45 | of modified code in any form. You may choose to destribute patch files, which can be applied to officially distributed
46 | code. Any the derivative products, must be distributed under the same conditions as specified in this agreement unless
47 | a separate commercial license is obtained from Securics Inc or its designates.
48 |
49 | As a condition of using this source code, you agree not to assert any patents or copyrights against the owners or any of
50 | the Owners’ licensees for use of derivative products. Any derivative products must include a copy of license and
51 | instructions for accessing the orignal source. You must also include attribution to the authors in any publication that
52 | results from the use of this code or data derived from the code. Any papers/research/report based on results that uses
53 | this software must cite:
54 |
55 | @article{Scheirer_2011_TPAMI,
56 | author = {Walter J. Scheirer and Anderson Rocha and Ross Michaels and Terrance E. Boult},
57 | title = {Meta-Recognition: The Theory and Practice of Recognition Score Analysis},
58 | journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI)},
59 | volume = {33},
60 | issue = {8},
61 | pages = {1689--1695},
62 | year = {2011}
63 | }
64 |
65 | Parts of this technology are subject to SBIR data rights and as described in DFARS 252.227-7018 (June 1995) SBIR Data Rights which apply to Contract Number: N00014-11-C-0243 and STTR N00014-07-M-0421 to Securics Inc, 1870 Austin Bluffs Parkway, Colorado Springs, CO 80918
66 |
67 | The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights in Noncommercial Technical Data and Computer Software-Small Business Innovative Research (SBIR) Program clause contained in the above identified contract. Expiration of SBIR Data Rights: Expires four years after completion of the above cited project work for this or any other follow-on SBIR contract, whichever is later.
68 |
69 | No restrictions on government use apply after the expiration date shown above. Any reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce the markings.
70 |
71 | This license includes other conditions that should be read carefully. This SOFWARE usage agreement (the "Agreement") applies to the libMR and is between YOU and the Licensor
72 |
73 | 1. DEFINITIONS
74 |
75 | "Software" means all or any portion of the human-readable source code files of the software programs including without limitation, associated flow charts, algorithms, comments and other written instructions and technical documentation, and all corrections, updates, and new versions incorporated into such programs.
76 |
77 | “Derivative Work” means a work based upon the Software, such as a revision, modification, translation, abridgement, condensation, expansion, collection, compilation, or any other form in which the Software may be recast, transformed, adapted, or distributed as a part of a larger work and which, if prepared without proper authorization would constitute a copyright infringement. If identifiable sections of that work are not derived from the Software, and can be reasonably considered independent and separate works in themselves, then they are not considered Derivative Work.
78 |
79 | "Personal Use" means use of Software and/or Derivative Work by an individual solely for his or her personal, private and non-commercial use. An individual's use in his or her capacity as an officer, employee, member, independent contractor or agent of a corporation, business or organization does not qualify as Personal Use.
80 |
81 | "You" or "Your" means an individual or a legal entity exercising rights under this License. For legal entities, "You" or "Your" includes any non-profit entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the beneficial ownership of such entity.
82 |
83 | 2. GRANT OF LICENSE:
84 |
85 | WHEREAS, the Licensor, desires to aid the academic and non-commercial research community and raise awareness of the PATENTED INVENTION and thereby agrees to grant a limited copyright license to the SOFTWARE for research and non-commercial purposes only, with the Owners retaining all ownership rights in the PATENTED INVENTION and the SOFTWARE;
86 |
87 | THEREFORE:
88 | The Licensor grants, and You accept, a personal, nonexclusive, nontransferable license:
89 |
90 | a) to use Software, at no charge, in accordance with the terms herein, solely for (i) Personal Use, or (ii) academic or non-commercial research, development and deployment; and
91 |
92 | b) to develop Derivative Works that may be used solely for (i) Personal Use or (ii) academic or non-commercial research, development and deployment; and
93 |
94 | c) to copy, distribute and sublicense Software and Derivative Works solely in accordance with the terms herein. Any Software or Derivative Works distributed shall be pursuant to a license agreement that contains all of the terms herein; and shall contain prominent notices stating how the Software, Derivative Works, or documentation was changed, the author and date of any such change and require acknowledgement of the orginal software/publicaitons by any users of the Derivative Works.
95 |
96 | d) You acknowledge that the Software is a valuable, proprietary asset of The Owners. You shall not market or sell the Software or Derivative Works.
97 |
98 | 3. LICENSE EXCLUSIONS
99 |
100 | a) EXCEPT AS EXPRESSLY PROVIDED HEREIN, YOU SHALL MAKE NO OTHER USE OF THE SOFTWARE.
101 |
102 | b) You must obtain permission from The Licensor before receiving payment for distribution of or services using the Software or Derivative Works.
103 |
104 | c) You shall not allege or enjoin infringement or misappropriation by The Licensor in any Derivative Works, or by any third party obtaining Derivative Works, prepared by The Licensor and under license from The Licensor.
105 |
106 |
107 | 4. TITLE AND PROTECTION OF SOFTWARE
108 |
109 | a) The Owners retains all title, right and interest to the Software and the underlying patents.
110 |
111 | b) Except for the Software, You retain all title, right and interest to the Derivative Works, subject to the terms of this Agreement.
112 |
113 | 5. NO REPRESENTATIONS
114 |
115 | THE OWNERS DISCLAIMS ALL OTHER REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
116 |
117 |
118 | 6. ATTRIBUTION
119 |
120 | a) You agree to retain and reproduce in all copies of Software the copyright and other proprietary notices and disclaimers as they appear in the Software, and keep intact all notices in the Software that refer to this License.
121 |
122 | b) You agree to provide attribution to the authors of this Software in any article based on research performed using Software or Derivative Works or with any distribution of Software or Derivative works.
123 |
124 | 7. DEFAULT
125 |
126 | If YOU fail to perform any of its obligations under this Agreement, The Licensor, in addition to any other rights available to it under law or equity, may terminate this Agreement and the licenses granted hereunder by written notice to You. Unless otherwise provided in this Agreement, remedies shall be cumulative and there shall be no obligation to exercise a particular remedy.
127 |
128 | 8. TERMINATION
129 |
130 | a) In the event that this Agreement is terminated, any sublicenses granted or Derivative Works distributed by Licensee shall remain in full force and effect.
131 |
132 | b) Within thirty (30) days of termination, You shall return to The Licensor or certify in writing to The Licensor that all copies or partial copies of Software in Your possession or control have been destroyed. c) In addition to this section, the sections entitled "Title and Protection of Software "No Representations" and “Limitation of Liability" shall survive termination of this Agreement.
133 |
134 | 9. GENERAL
135 | a) No agency, partnership or employment is created by this Agreement.
136 |
137 | b) You may not use any of The Owners’ names, the terms in Meta-Recognition, or W-score in any advertising, public relations or media release without the prior written consent of the Owner.
138 |
139 | c) This Agreement shall be governed by the laws of the State of Colorado. Venue for any action or proceeding shall be Denver, Colorado. This Agreement constitutes the entire agreement between the parties and may only be modified by a written instrument signed by each parties authorized officers.
140 |
141 |
142 | References:
143 | [1] Walter J. Scheirer*, Lalit P. Jain*, Terrance E. Boult: Probability Models for Open Set Recognition. IEEE Trans. Pattern Anal. Mach. Intell. (2014)
144 | [2] Walter J. Scheirer, Anderson de Rezende Rocha, Archana Sapkota, Terrance E. Boult: Toward Open Set Recognition. IEEE Trans. Pattern Anal. Mach. Intell. 35(7): 1757-1772 (2013)
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #LIBMR_DIR should be absolute path, not relative (no ..)
2 | LIBMR_DIR = /Users/macuser/lalitphd/WSVM/libsvm-openset/libMR
3 |
4 | ifeq ($(OS),Windows_NT)
5 | CFLAGS += -D WIN32
6 | ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
7 | CFLAGS += -D AMD64
8 | LIBSUFFIX = .dll
9 | endif
10 | ifeq ($(PROCESSOR_ARCHITECTURE),x86)
11 | CFLAGS += -D IA32
12 | LIBSUFFIX = .dll
13 | endif
14 | else
15 | UNAME_S := $(shell uname -s)
16 | ifeq ($(UNAME_S),Linux)
17 | CFLAGS += -D LINUX -Wl,-rpath=$(LIBMR_DIR)/libMR/build/libMR/
18 | LIBSUFFIX = .so
19 | endif
20 | ifeq ($(UNAME_S),Darwin)
21 | CFLAGS += -D OSX
22 | LIBSUFFIX = .dylib
23 | endif
24 | endif
25 |
26 | CXX ?= g++ -g
27 | #CFLAGS = -Wall -Wconversion -g
28 |
29 | LIBMR_LIB = $(LIBMR_DIR)/libMR/build/libMR/libMR$(LIBSUFFIX)
30 | #LIBMR_LIB = build/libMR/libMR.so
31 |
32 | CFLAGS += -Wall -g -I $(LIBMR_DIR)/libMR
33 | CFLAGS += -O2 -fPIC
34 | SHVER = 2
35 |
36 | all: svm-train svm-predict svm-scale $(LIBMR_LIB)
37 |
38 | $(LIBMR_LIB): $(LIBMR_DIR)/libMR/MetaRecognition.h $(LIBMR_DIR)/libMR/MetaRecognition.cpp
39 | mkdir -p $(LIBMR_DIR)/libMR/build
40 | cd $(LIBMR_DIR)/libMR/build; cmake -DCMAKE_BUILD_TYPE=Debug $(LIBMR_DIR); make
41 |
42 |
43 |
44 | lib: svm.o $(LIBMR_LIB)
45 | $(CXX) -shared -dynamiclib svm.o $(LIBMR_LIB) -o libsvm.so.$(SHVER)
46 |
47 | svm-predict: svm-predict.cpp svm.o $(LIBMR_LIB)
48 | $(CXX) $(CFLAGS) svm-predict.cpp svm.o $(LIBMR_LIB) -o svm-predict -lm
49 | svm-train: svm-train.cpp svm.o $(LIBMR_LIB)
50 | $(CXX) $(CFLAGS) svm-train.cpp svm.o $(LIBMR_LIB) -o svm-train -lm
51 | svm-scale: svm-scale.c $(LIBMR_LIB)
52 | $(CXX) $(CFLAGS) svm-scale.c $(LIBMR_LIB) -o svm-scale
53 | svm.o: svm.cpp svm.h
54 | $(CXX) $(CFLAGS) -c svm.cpp
55 | clean:
56 | rm -fr *~ svm.o svm-train svm-predict svm-scale libsvm.so.$(SHVER) $(LIBMR_DIR)/libMR/build
57 |
--------------------------------------------------------------------------------
/Makefile.win:
--------------------------------------------------------------------------------
1 | #You must ensure nmake.exe, cl.exe, link.exe are in system path.
2 | #VCVARS32.bat
3 | #Under dosbox prompt
4 | #nmake -f Makefile.win
5 |
6 | ##########################################
7 | CXX = cl.exe
8 | CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE
9 | TARGET = windows
10 |
11 | all: $(TARGET)\svm-train.exe $(TARGET)\svm-predict.exe $(TARGET)\svm-scale.exe $(TARGET)\svm-toy.exe lib
12 |
13 | $(TARGET)\svm-predict.exe: svm.h svm-predict.c svm.obj
14 | $(CXX) $(CFLAGS) svm-predict.c svm.obj -Fe$(TARGET)\svm-predict.exe
15 |
16 | $(TARGET)\svm-train.exe: svm.h svm-train.c svm.obj
17 | $(CXX) $(CFLAGS) svm-train.c svm.obj -Fe$(TARGET)\svm-train.exe
18 |
19 | $(TARGET)\svm-scale.exe: svm.h svm-scale.c
20 | $(CXX) $(CFLAGS) svm-scale.c -Fe$(TARGET)\svm-scale.exe
21 |
22 | $(TARGET)\svm-toy.exe: svm.h svm.obj svm-toy\windows\svm-toy.cpp
23 | $(CXX) $(CFLAGS) svm-toy\windows\svm-toy.cpp svm.obj user32.lib gdi32.lib comdlg32.lib -Fe$(TARGET)\svm-toy.exe
24 |
25 | svm.obj: svm.cpp svm.h
26 | $(CXX) $(CFLAGS) -c svm.cpp
27 |
28 | lib: svm.cpp svm.h svm.def
29 | $(CXX) $(CFLAGS) -LD svm.cpp -Fe$(TARGET)\libsvm -link -DEF:svm.def
30 |
31 | clean:
32 | -erase /Q *.obj $(TARGET)\.
33 |
34 |
--------------------------------------------------------------------------------
/README-libsvm-openset:
--------------------------------------------------------------------------------
1 | The libsvm-openset package extends libsvm to support openset recognition using the PI-SVM, WSVM and 1-vs-set extension described in [1] [2] and [3] respectively. libsvm-openset incoporates all libsvm functionality PI-SVM described in [1] + WSVM described in [2] + 1-vs-set described in [3].
2 |
3 |
4 | This package an extension to the well known libsvm package (see README for info on libsvm) and extends support for linear, poly, RBG and sigmod kernels (-t [0-3]). It should work with customer kernels, we just did not test that).
5 |
6 | PI-SVM/PI-OSVM functionality described in [1] in libsvm-openset:
7 | The extension uses the same command-line processing with a few added fields:
8 | In svm-train:
9 | -s 9 for the PI-OSVM based on one-class svms
10 | -s 10 for the PI-SVM based on 1-vs-rest binary svms
11 | In svm-predict:
12 | -P specify thresholded probability value to reject sample as unknowns for WSVM (default 0.0)
13 |
14 | To use WSVM in libsvm-openset:
15 | ************ Training
16 | ./svm-train -s 9 -t 0 TrainingDataFile ModelFile
17 | ./svm-train -s 10 -t 0 TrainingDataFile ModelFile
18 | where TrainingDataFile is training file in libsvm format. "ModelFile" will be genrated using one-class svms for PI-OSVM (-s 9 option) and 1-vs-rest SVM binary svms for PI-SVM (-s 10 option) respectively. Both PI-SVM and PI-OSVM estimates probability of inclusion for the single class.
19 | ************ Predicing Using model files ("ModelFile")
20 | ./svm-predict -P 0.1 TestDataFile ModelFile outputfile
21 | where TestDataFile is testing file in libsvm format. ModelFile is file generated during training.
22 | -P specify the threshold to consider for rejecting samples as unknown in PI-SVM and PI-OSVM.
23 |
24 |
25 | WSVM functionality described in [2] in libsvm-openset:
26 | The extension uses the same command-line processing with a few added fields:
27 | In svm-train:
28 | -s 8 for the WSVM based on 1-vs-rest binary svms
29 | In svm-predict:
30 | -P specify thresholded probability value to reject sample as unknowns for WSVM (default 0.0)
31 | -C specify thresholded probability value to reject sample as unknowns for CAP model in WSVM (default 0.0)
32 |
33 | To use WSVM in libsvm-openset:
34 | ************ Training
35 | ./svm-train -s 8 -t 0 TrainingDataFile ModelFile
36 | where if TrainingDataFile is training file in libsvm format. Two file "ModelFile" and "ModelFile_one_wsvm" will be genrated using 1-vs-rest SVM and one-class SVM (CAP) respectively for WSVM.
37 | ************ Predicing Using two model files ("ModelFile" and "ModelFile_one_wsvm")
38 | ./svm-predict -P 0.1 -C 0.001 TestDataFile ModelFile outputfile
39 | where TestDataFile is testing file in libsvm format. ModelFile is file generated during training. ./svm-predict by default looks for ModelFile_one_wsvm file generated for CAP model in WSVM training.
40 | -P specify the threshold to consider for rejecting samples as unknown in WSVM.
41 | -C specify the minimum threshold to consider for any sample in CAP model.
42 |
43 |
44 | 1-vs-set functionality described in [3] in libsvm-openset:
45 | The extension uses the same command-line processing with a few added fields:
46 | In svm-train:
47 | -s 7 for the 1-vs-set based on "1-vs-all" binary svms (which is the generally recommended model)
48 | -s 5 for the 1-vs-set based on one class svm (provides better generalization of one-class, but not truly a discriminative model )
49 | -B optarg Defines the beta of fmeasure used in the balanced Balanced risk discussed in the paper.
50 | -G near_pessure far_pressure (which allows changes to the "pressure" of the open-set formulation. Increasing pressure causes increased generalization, negative pressures cause increased specialization (e.g. you know you only had a few negative training classes).
51 | -V logfilename (for verbose logs/debugging related to the actual openset optimization stages
52 |
53 | To use 1-vs-set (only linear and RBF kernels supported) in libsvm-openset:
54 | ************ Training using Pos/Negative or multi-class Files once *****************
55 | ./svm-train -s 5 -t 0 TrainingDataFile
56 | where if TrainingDataFile is a mixed file with 1 for positive, -1 for negative
57 | This produces TrainingDataFile.model.1
58 | if TrainingDataFile is a mixed file with multiple class labels (1, 2 3.. 10)
59 | This produces TrainingDataFile.model.1 TrainingDataFile.model.2.. TrainingDataFile.model.10
60 | ************ Predicing Using single Model Files (against a multi-class or binary test file) *****************
61 | ./svm-predict -o testingDataFile TrainingDataFile.model.7 outpufile
62 | outputfle has lines of the format predicted_label decision_score (target_label)
63 | if the model has an index other than 1, then the testfile must be in multi-class format (rows start with class label).
64 | ************ Predicing using multiple Model Files all at once *****************
65 | ./svm-predict -o testingDataFile TrainingDataFile.model. outpufile
66 | outputfle has lines of the format predicted_label decision_score (target_label)
67 | (Note the trailing . after model.. that tell it to use all models could also do .* but must escape the *)
68 |
69 |
70 |
71 |
72 | Installation:
73 | In order to compile WSVM functionality incorporated in libsvm-openset, libMR library available at http://www.metarecognition.com/libmr-license is needed. Once libMR.zip is copied after accepting its license, unzip libMR, copy libMR in libsvm-openset and build libMR.
74 |
75 | libMR Quick Build Instruction:
76 | This needs CMake (version > 2.8)
77 | Quick build instructions for linux/Mac:
78 | $> tar -zxf libMR.tgz
79 | $> cd libMR
80 | %You can edit the CMakeLists.txt in libMR level, to change install dir if desired
81 | $> mkdir build; % or where you like to build it
82 | $> cd build
83 | $> cmake -DCMAKE_BUILD_TYPE=Debug ..
84 | $> make
85 |
86 | libsvm-openset Quick Build Instruction:
87 | Once libMR is build, next step is to specify the absolute path of libMR directory in Makefile available in libsvm-openset. Paste the absolute path of libMR folder in variable "LIBMR_DIR" in Makefile (line 2 of Makefile). For example: LIBMR_DIR = /Users/username/libsvm-openset/libMR
88 | On linux/mac systems, type `make' to build the `svm-train' and `svm-predict' programs. Run them without arguments to show the usages of them.
89 | e.g:
90 | $> cd libsvm-openset
91 | $> make
92 | $> ./svm-train
93 | $> ./svm-predict
94 |
95 |
96 |
97 | References:
98 | [1] Lalit P. Jain, Walter J. Scheirer, Terrance E. Boult: Multi-Class Open Set Recognition Using Probability of Inclusion. European Conference on Computer Vision (ECCV 2014), September 2014, Zurich, Switzerland.
99 |
100 | [2] Walter J. Scheirer*, Lalit P. Jain*, Terrance E. Boult: Probability Models for Open Set Recognition. IEEE Trans. Pattern Anal. Mach. Intell. (2014)
101 |
102 | [3] Walter J. Scheirer, Anderson de Rezende Rocha, Archana Sapkota, Terrance E. Boult: Toward Open Set Recognition. IEEE Trans. Pattern Anal. Mach. Intell. 35(7): 1757-1772 (2013)
--------------------------------------------------------------------------------
/java/Makefile:
--------------------------------------------------------------------------------
1 | .SUFFIXES: .class .java
2 | FILES = libsvm/svm.class libsvm/svm_model.class libsvm/svm_node.class \
3 | libsvm/svm_parameter.class libsvm/svm_problem.class \
4 | libsvm/svm_print_interface.class \
5 | svm_train.class svm_predict.class svm_toy.class svm_scale.class
6 |
7 | #JAVAC = jikes
8 | JAVAC_FLAGS = -target 1.5 -source 1.5
9 | JAVAC = javac
10 | # JAVAC_FLAGS =
11 |
12 | all: $(FILES)
13 | jar cvf libsvm.jar *.class libsvm/*.class
14 |
15 | .java.class:
16 | $(JAVAC) $(JAVAC_FLAGS) $<
17 |
18 | libsvm/svm.java: libsvm/svm.m4
19 | m4 libsvm/svm.m4 > libsvm/svm.java
20 |
21 | clean:
22 | rm -f libsvm/*.class *.class *.jar libsvm/*~ *~ libsvm/svm.java
23 |
24 | dist: clean all
25 | rm *.class libsvm/*.class
26 |
--------------------------------------------------------------------------------
/java/libsvm.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ljain2/libsvm-openset/122298cf40c56d09e83c826024340854177ba5f8/java/libsvm.jar
--------------------------------------------------------------------------------
/java/libsvm/svm_model.java:
--------------------------------------------------------------------------------
1 | //
2 | // svm_model
3 | //
4 | package libsvm;
5 | public class svm_model implements java.io.Serializable
6 | {
7 | public svm_parameter param; // parameter
8 | public int nr_class; // number of classes, = 2 in regression/one class svm
9 | public int l; // total #SV
10 | public svm_node[][] SV; // SVs (SV[l])
11 | public double[][] sv_coef; // coefficients for SVs in decision functions (sv_coef[k-1][l])
12 | public double[] rho; // constants in decision functions (rho[k*(k-1)/2])
13 | public double[] probA; // pariwise probability information
14 | public double[] probB;
15 |
16 | // for classification only
17 |
18 | public int[] label; // label of each class (label[k])
19 | public int[] nSV; // number of SVs for each class (nSV[k])
20 | // nSV[0] + nSV[1] + ... + nSV[k-1] = l
21 | };
22 |
--------------------------------------------------------------------------------
/java/libsvm/svm_node.java:
--------------------------------------------------------------------------------
1 | package libsvm;
2 | public class svm_node implements java.io.Serializable
3 | {
4 | public int index;
5 | public double value;
6 | }
7 |
--------------------------------------------------------------------------------
/java/libsvm/svm_parameter.java:
--------------------------------------------------------------------------------
1 | package libsvm;
2 | public class svm_parameter implements Cloneable,java.io.Serializable
3 | {
4 | /* svm_type */
5 | public static final int C_SVC = 0;
6 | public static final int NU_SVC = 1;
7 | public static final int ONE_CLASS = 2;
8 | public static final int EPSILON_SVR = 3;
9 | public static final int NU_SVR = 4;
10 |
11 | /* kernel_type */
12 | public static final int LINEAR = 0;
13 | public static final int POLY = 1;
14 | public static final int RBF = 2;
15 | public static final int SIGMOID = 3;
16 | public static final int PRECOMPUTED = 4;
17 |
18 | public int svm_type;
19 | public int kernel_type;
20 | public int degree; // for poly
21 | public double gamma; // for poly/rbf/sigmoid
22 | public double coef0; // for poly/sigmoid
23 |
24 | // these are for training only
25 | public double cache_size; // in MB
26 | public double eps; // stopping criteria
27 | public double C; // for C_SVC, EPSILON_SVR and NU_SVR
28 | public int nr_weight; // for C_SVC
29 | public int[] weight_label; // for C_SVC
30 | public double[] weight; // for C_SVC
31 | public double nu; // for NU_SVC, ONE_CLASS, and NU_SVR
32 | public double p; // for EPSILON_SVR
33 | public int shrinking; // use the shrinking heuristics
34 | public int probability; // do probability estimates
35 |
36 | public Object clone()
37 | {
38 | try
39 | {
40 | return super.clone();
41 | } catch (CloneNotSupportedException e)
42 | {
43 | return null;
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/java/libsvm/svm_print_interface.java:
--------------------------------------------------------------------------------
1 | package libsvm;
2 | public interface svm_print_interface
3 | {
4 | public void print(String s);
5 | }
6 |
--------------------------------------------------------------------------------
/java/libsvm/svm_problem.java:
--------------------------------------------------------------------------------
1 | package libsvm;
2 | public class svm_problem implements java.io.Serializable
3 | {
4 | public int l;
5 | public double[] y;
6 | public svm_node[][] x;
7 | }
8 |
--------------------------------------------------------------------------------
/java/svm_predict.java:
--------------------------------------------------------------------------------
1 | import libsvm.*;
2 | import java.io.*;
3 | import java.util.*;
4 |
5 | class svm_predict {
6 | private static double atof(String s)
7 | {
8 | return Double.valueOf(s).doubleValue();
9 | }
10 |
11 | private static int atoi(String s)
12 | {
13 | return Integer.parseInt(s);
14 | }
15 |
16 | private static void predict(BufferedReader input, DataOutputStream output, svm_model model, int predict_probability) throws IOException
17 | {
18 | int correct = 0;
19 | int total = 0;
20 | double error = 0;
21 | double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
22 |
23 | int svm_type=svm.svm_get_svm_type(model);
24 | int nr_class=svm.svm_get_nr_class(model);
25 | double[] prob_estimates=null;
26 |
27 | if(predict_probability == 1)
28 | {
29 | if(svm_type == svm_parameter.EPSILON_SVR ||
30 | svm_type == svm_parameter.NU_SVR)
31 | {
32 | System.out.print("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma="+svm.svm_get_svr_probability(model)+"\n");
33 | }
34 | else
35 | {
36 | int[] labels=new int[nr_class];
37 | svm.svm_get_labels(model,labels);
38 | prob_estimates = new double[nr_class];
39 | output.writeBytes("labels");
40 | for(int j=0;j=argv.length-2)
129 | exit_with_help();
130 | try
131 | {
132 | BufferedReader input = new BufferedReader(new FileReader(argv[i]));
133 | DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(argv[i+2])));
134 | svm_model model = svm.svm_load_model(argv[i+1]);
135 | if(predict_probability == 1)
136 | {
137 | if(svm.svm_check_probability_model(model)==0)
138 | {
139 | System.err.print("Model does not support probabiliy estimates\n");
140 | System.exit(1);
141 | }
142 | }
143 | else
144 | {
145 | if(svm.svm_check_probability_model(model)!=0)
146 | {
147 | System.out.print("Model supports probability estimates, but disabled in prediction.\n");
148 | }
149 | }
150 | predict(input,output,model,predict_probability);
151 | input.close();
152 | output.close();
153 | }
154 | catch(FileNotFoundException e)
155 | {
156 | exit_with_help();
157 | }
158 | catch(ArrayIndexOutOfBoundsException e)
159 | {
160 | exit_with_help();
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/java/svm_scale.java:
--------------------------------------------------------------------------------
1 | import libsvm.*;
2 | import java.io.*;
3 | import java.util.*;
4 | import java.text.DecimalFormat;
5 |
6 | class svm_scale
7 | {
8 | private String line = null;
9 | private double lower = -1.0;
10 | private double upper = 1.0;
11 | private double y_lower;
12 | private double y_upper;
13 | private boolean y_scaling = false;
14 | private double[] feature_max;
15 | private double[] feature_min;
16 | private double y_max = -Double.MAX_VALUE;
17 | private double y_min = Double.MAX_VALUE;
18 | private int max_index;
19 | private long num_nonzeros = 0;
20 | private long new_num_nonzeros = 0;
21 |
22 | private static void exit_with_help()
23 | {
24 | System.out.print(
25 | "Usage: svm-scale [options] data_filename\n"
26 | +"options:\n"
27 | +"-l lower : x scaling lower limit (default -1)\n"
28 | +"-u upper : x scaling upper limit (default +1)\n"
29 | +"-y y_lower y_upper : y scaling limits (default: no y scaling)\n"
30 | +"-s save_filename : save scaling parameters to save_filename\n"
31 | +"-r restore_filename : restore scaling parameters from restore_filename\n"
32 | );
33 | System.exit(1);
34 | }
35 |
36 | private BufferedReader rewind(BufferedReader fp, String filename) throws IOException
37 | {
38 | fp.close();
39 | return new BufferedReader(new FileReader(filename));
40 | }
41 |
42 | private void output_target(double value)
43 | {
44 | if(y_scaling)
45 | {
46 | if(value == y_min)
47 | value = y_lower;
48 | else if(value == y_max)
49 | value = y_upper;
50 | else
51 | value = y_lower + (y_upper-y_lower) *
52 | (value-y_min) / (y_max-y_min);
53 | }
54 |
55 | System.out.print(value + " ");
56 | }
57 |
58 | private void output(int index, double value)
59 | {
60 | /* skip single-valued attribute */
61 | if(feature_max[index] == feature_min[index])
62 | return;
63 |
64 | if(value == feature_min[index])
65 | value = lower;
66 | else if(value == feature_max[index])
67 | value = upper;
68 | else
69 | value = lower + (upper-lower) *
70 | (value-feature_min[index])/
71 | (feature_max[index]-feature_min[index]);
72 |
73 | if(value != 0)
74 | {
75 | System.out.print(index + ":" + value + " ");
76 | new_num_nonzeros++;
77 | }
78 | }
79 |
80 | private String readline(BufferedReader fp) throws IOException
81 | {
82 | line = fp.readLine();
83 | return line;
84 | }
85 |
86 | private void run(String []argv) throws IOException
87 | {
88 | int i,index;
89 | BufferedReader fp = null, fp_restore = null;
90 | String save_filename = null;
91 | String restore_filename = null;
92 | String data_filename = null;
93 |
94 |
95 | for(i=0;i lower) || (y_scaling && !(y_upper > y_lower)))
118 | {
119 | System.err.println("inconsistent lower/upper specification");
120 | System.exit(1);
121 | }
122 | if(restore_filename != null && save_filename != null)
123 | {
124 | System.err.println("cannot use -r and -s simultaneously");
125 | System.exit(1);
126 | }
127 |
128 | if(argv.length != i+1)
129 | exit_with_help();
130 |
131 | data_filename = argv[i];
132 | try {
133 | fp = new BufferedReader(new FileReader(data_filename));
134 | } catch (Exception e) {
135 | System.err.println("can't open file " + data_filename);
136 | System.exit(1);
137 | }
138 |
139 | /* assumption: min index of attributes is 1 */
140 | /* pass 1: find out max index of attributes */
141 | max_index = 0;
142 |
143 | if(restore_filename != null)
144 | {
145 | int idx, c;
146 |
147 | try {
148 | fp_restore = new BufferedReader(new FileReader(restore_filename));
149 | }
150 | catch (Exception e) {
151 | System.err.println("can't open file " + restore_filename);
152 | System.exit(1);
153 | }
154 | if((c = fp_restore.read()) == 'y')
155 | {
156 | fp_restore.readLine();
157 | fp_restore.readLine();
158 | fp_restore.readLine();
159 | }
160 | fp_restore.readLine();
161 | fp_restore.readLine();
162 |
163 | String restore_line = null;
164 | while((restore_line = fp_restore.readLine())!=null)
165 | {
166 | StringTokenizer st2 = new StringTokenizer(restore_line);
167 | idx = Integer.parseInt(st2.nextToken());
168 | max_index = Math.max(max_index, idx);
169 | }
170 | fp_restore = rewind(fp_restore, restore_filename);
171 | }
172 |
173 | while (readline(fp) != null)
174 | {
175 | StringTokenizer st = new StringTokenizer(line," \t\n\r\f:");
176 | st.nextToken();
177 | while(st.hasMoreTokens())
178 | {
179 | index = Integer.parseInt(st.nextToken());
180 | max_index = Math.max(max_index, index);
181 | st.nextToken();
182 | num_nonzeros++;
183 | }
184 | }
185 |
186 | try {
187 | feature_max = new double[(max_index+1)];
188 | feature_min = new double[(max_index+1)];
189 | } catch(OutOfMemoryError e) {
190 | System.err.println("can't allocate enough memory");
191 | System.exit(1);
192 | }
193 |
194 | for(i=0;i<=max_index;i++)
195 | {
196 | feature_max[i] = -Double.MAX_VALUE;
197 | feature_min[i] = Double.MAX_VALUE;
198 | }
199 |
200 | fp = rewind(fp, data_filename);
201 |
202 | /* pass 2: find out min/max value */
203 | while(readline(fp) != null)
204 | {
205 | int next_index = 1;
206 | double target;
207 | double value;
208 |
209 | StringTokenizer st = new StringTokenizer(line," \t\n\r\f:");
210 | target = Double.parseDouble(st.nextToken());
211 | y_max = Math.max(y_max, target);
212 | y_min = Math.min(y_min, target);
213 |
214 | while (st.hasMoreTokens())
215 | {
216 | index = Integer.parseInt(st.nextToken());
217 | value = Double.parseDouble(st.nextToken());
218 |
219 | for (i = next_index; i num_nonzeros)
337 | System.err.print(
338 | "Warning: original #nonzeros " + num_nonzeros+"\n"
339 | +" new #nonzeros " + new_num_nonzeros+"\n"
340 | +"Use -l 0 if many original feature values are zeros\n");
341 |
342 | fp.close();
343 | }
344 |
345 | public static void main(String argv[]) throws IOException
346 | {
347 | svm_scale s = new svm_scale();
348 | s.run(argv);
349 | }
350 | }
351 |
--------------------------------------------------------------------------------
/java/svm_train.java:
--------------------------------------------------------------------------------
1 | import libsvm.*;
2 | import java.io.*;
3 | import java.util.*;
4 |
5 | class svm_train {
6 | private svm_parameter param; // set by parse_command_line
7 | private svm_problem prob; // set by read_problem
8 | private svm_model model;
9 | private String input_file_name; // set by parse_command_line
10 | private String model_file_name; // set by parse_command_line
11 | private String error_msg;
12 | private int cross_validation;
13 | private int nr_fold;
14 |
15 | private static svm_print_interface svm_print_null = new svm_print_interface()
16 | {
17 | public void print(String s) {}
18 | };
19 |
20 | private static void exit_with_help()
21 | {
22 | System.out.print(
23 | "Usage: svm_train [options] training_set_file [model_file]\n"
24 | +"options:\n"
25 | +"-s svm_type : set type of SVM (default 0)\n"
26 | +" 0 -- C-SVC\n"
27 | +" 1 -- nu-SVC\n"
28 | +" 2 -- one-class SVM\n"
29 | +" 3 -- epsilon-SVR\n"
30 | +" 4 -- nu-SVR\n"
31 | +"-t kernel_type : set type of kernel function (default 2)\n"
32 | +" 0 -- linear: u'*v\n"
33 | +" 1 -- polynomial: (gamma*u'*v + coef0)^degree\n"
34 | +" 2 -- radial basis function: exp(-gamma*|u-v|^2)\n"
35 | +" 3 -- sigmoid: tanh(gamma*u'*v + coef0)\n"
36 | +" 4 -- precomputed kernel (kernel values in training_set_file)\n"
37 | +"-d degree : set degree in kernel function (default 3)\n"
38 | +"-g gamma : set gamma in kernel function (default 1/num_features)\n"
39 | +"-r coef0 : set coef0 in kernel function (default 0)\n"
40 | +"-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)\n"
41 | +"-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)\n"
42 | +"-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)\n"
43 | +"-m cachesize : set cache memory size in MB (default 100)\n"
44 | +"-e epsilon : set tolerance of termination criterion (default 0.001)\n"
45 | +"-h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)\n"
46 | +"-b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)\n"
47 | +"-wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)\n"
48 | +"-v n : n-fold cross validation mode\n"
49 | +"-q : quiet mode (no outputs)\n"
50 | );
51 | System.exit(1);
52 | }
53 |
54 | private void do_cross_validation()
55 | {
56 | int i;
57 | int total_correct = 0;
58 | double total_error = 0;
59 | double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
60 | double[] target = new double[prob.l];
61 |
62 | svm.svm_cross_validation(prob,param,nr_fold,target);
63 | if(param.svm_type == svm_parameter.EPSILON_SVR ||
64 | param.svm_type == svm_parameter.NU_SVR)
65 | {
66 | for(i=0;i=argv.length)
166 | exit_with_help();
167 | switch(argv[i-1].charAt(1))
168 | {
169 | case 's':
170 | param.svm_type = atoi(argv[i]);
171 | break;
172 | case 't':
173 | param.kernel_type = atoi(argv[i]);
174 | break;
175 | case 'd':
176 | param.degree = atoi(argv[i]);
177 | break;
178 | case 'g':
179 | param.gamma = atof(argv[i]);
180 | break;
181 | case 'r':
182 | param.coef0 = atof(argv[i]);
183 | break;
184 | case 'n':
185 | param.nu = atof(argv[i]);
186 | break;
187 | case 'm':
188 | param.cache_size = atof(argv[i]);
189 | break;
190 | case 'c':
191 | param.C = atof(argv[i]);
192 | break;
193 | case 'e':
194 | param.eps = atof(argv[i]);
195 | break;
196 | case 'p':
197 | param.p = atof(argv[i]);
198 | break;
199 | case 'h':
200 | param.shrinking = atoi(argv[i]);
201 | break;
202 | case 'b':
203 | param.probability = atoi(argv[i]);
204 | break;
205 | case 'q':
206 | print_func = svm_print_null;
207 | i--;
208 | break;
209 | case 'v':
210 | cross_validation = 1;
211 | nr_fold = atoi(argv[i]);
212 | if(nr_fold < 2)
213 | {
214 | System.err.print("n-fold cross validation: n must >= 2\n");
215 | exit_with_help();
216 | }
217 | break;
218 | case 'w':
219 | ++param.nr_weight;
220 | {
221 | int[] old = param.weight_label;
222 | param.weight_label = new int[param.nr_weight];
223 | System.arraycopy(old,0,param.weight_label,0,param.nr_weight-1);
224 | }
225 |
226 | {
227 | double[] old = param.weight;
228 | param.weight = new double[param.nr_weight];
229 | System.arraycopy(old,0,param.weight,0,param.nr_weight-1);
230 | }
231 |
232 | param.weight_label[param.nr_weight-1] = atoi(argv[i-1].substring(2));
233 | param.weight[param.nr_weight-1] = atof(argv[i]);
234 | break;
235 | default:
236 | System.err.print("Unknown option: " + argv[i-1] + "\n");
237 | exit_with_help();
238 | }
239 | }
240 |
241 | svm.svm_set_print_string_function(print_func);
242 |
243 | // determine filenames
244 |
245 | if(i>=argv.length)
246 | exit_with_help();
247 |
248 | input_file_name = argv[i];
249 |
250 | if(i vy = new Vector();
266 | Vector vx = new Vector();
267 | int max_index = 0;
268 |
269 | while(true)
270 | {
271 | String line = fp.readLine();
272 | if(line == null) break;
273 |
274 | StringTokenizer st = new StringTokenizer(line," \t\n\r\f:");
275 |
276 | vy.addElement(atof(st.nextToken()));
277 | int m = st.countTokens()/2;
278 | svm_node[] x = new svm_node[m];
279 | for(int j=0;j0) max_index = Math.max(max_index, x[m-1].index);
286 | vx.addElement(x);
287 | }
288 |
289 | prob = new svm_problem();
290 | prob.l = vy.size();
291 | prob.x = new svm_node[prob.l][];
292 | for(int i=0;i 0)
299 | param.gamma = 1.0/max_index;
300 |
301 | if(param.kernel_type == svm_parameter.PRECOMPUTED)
302 | for(int i=0;i max_index)
310 | {
311 | System.err.print("Wrong input format: sample_serial_number out of range\n");
312 | System.exit(1);
313 | }
314 | }
315 |
316 | fp.close();
317 | }
318 | }
319 |
--------------------------------------------------------------------------------
/java/test_applet.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/matlab/Makefile:
--------------------------------------------------------------------------------
1 | # This Makefile is used under Linux
2 |
3 | MATLABDIR ?= /usr/local/matlab
4 | # for Mac
5 | # MATLABDIR ?= /opt/local/matlab
6 |
7 | CXX ?= g++
8 | #CXX = g++-4.1
9 | CFLAGS = -Wall -Wconversion -O3 -fPIC -I$(MATLABDIR)/extern/include -I..
10 |
11 | MEX = $(MATLABDIR)/bin/mex
12 | MEX_OPTION = CC\#$(CXX) CXX\#$(CXX) CFLAGS\#"$(CFLAGS)" CXXFLAGS\#"$(CFLAGS)"
13 | # comment the following line if you use MATLAB on 32-bit computer
14 | MEX_OPTION += -largeArrayDims
15 | MEX_EXT = $(shell $(MATLABDIR)/bin/mexext)
16 |
17 | OCTAVEDIR ?= /usr/include/octave
18 | OCTAVE_MEX = env CC=$(CXX) mkoctfile
19 | OCTAVE_MEX_OPTION = --mex
20 | OCTAVE_MEX_EXT = mex
21 | OCTAVE_CFLAGS = -Wall -O3 -fPIC -I$(OCTAVEDIR) -I..
22 |
23 | all: matlab
24 |
25 | matlab: binary
26 |
27 | octave:
28 | @make MEX="$(OCTAVE_MEX)" MEX_OPTION="$(OCTAVE_MEX_OPTION)" \
29 | MEX_EXT="$(OCTAVE_MEX_EXT)" CFLAGS="$(OCTAVE_CFLAGS)" \
30 | binary
31 |
32 | binary: svmpredict.$(MEX_EXT) svmtrain.$(MEX_EXT) libsvmread.$(MEX_EXT) libsvmwrite.$(MEX_EXT)
33 |
34 | svmpredict.$(MEX_EXT): svmpredict.c ../svm.h ../svm.o svm_model_matlab.o
35 | $(MEX) $(MEX_OPTION) svmpredict.c ../svm.o svm_model_matlab.o
36 |
37 | svmtrain.$(MEX_EXT): svmtrain.c ../svm.h ../svm.o svm_model_matlab.o
38 | $(MEX) $(MEX_OPTION) svmtrain.c ../svm.o svm_model_matlab.o
39 |
40 | libsvmread.$(MEX_EXT): libsvmread.c
41 | $(MEX) $(MEX_OPTION) libsvmread.c
42 |
43 | libsvmwrite.$(MEX_EXT): libsvmwrite.c
44 | $(MEX) $(MEX_OPTION) libsvmwrite.c
45 |
46 | svm_model_matlab.o: svm_model_matlab.c ../svm.h
47 | $(CXX) $(CFLAGS) -c svm_model_matlab.c
48 |
49 | ../svm.o:
50 | cd ../; make svm.o
51 |
52 | clean:
53 | rm -f *~ *.o *.mex* *.obj ../svm.o
54 |
--------------------------------------------------------------------------------
/matlab/README:
--------------------------------------------------------------------------------
1 | -----------------------------------------
2 | --- MATLAB/OCTAVE interface of LIBSVM ---
3 | -----------------------------------------
4 |
5 | Table of Contents
6 | =================
7 |
8 | - Introduction
9 | - Installation
10 | - Usage
11 | - Returned Model Structure
12 | - Other Utilities
13 | - Examples
14 | - Additional Information
15 |
16 |
17 | Introduction
18 | ============
19 |
20 | This tool provides a simple interface to LIBSVM, a library for support vector
21 | machines (http://www.csie.ntu.edu.tw/~cjlin/libsvm). It is very easy to use as
22 | the usage and the way of specifying parameters are the same as that of LIBSVM.
23 |
24 | Installation
25 | ============
26 |
27 | On Unix systems, we recommend using GNU g++ as your
28 | compiler and type 'make' to build 'svmtrain.mexglx' and 'svmpredict.mexglx'.
29 | Note that we assume your MATLAB is installed in '/usr/local/matlab',
30 | if not, please change MATLABDIR in Makefile.
31 |
32 | Example:
33 | linux> make
34 |
35 | To use Octave, type 'make octave':
36 |
37 | Example:
38 | linux> make octave
39 |
40 | On Windows systems, pre-built binary files are already in the directory
41 | `..\windows', so no need to conduct installation. Now we include both
42 | 32bit binary files and 64bit binary files, but in future releases, we
43 | will provide binary files only for 64bit MATLAB on Windows. If you have
44 | modified the sources and would like to re-build the package, type
45 | 'mex -setup' in MATLAB to choose a compiler for mex first. Then type
46 | 'make' to start the installation.
47 |
48 | Example:
49 | matlab> mex -setup
50 | (ps: MATLAB will show the following messages to setup default compiler.)
51 | Please choose your compiler for building external interface (MEX) files:
52 | Would you like mex to locate installed compilers [y]/n? y
53 | Select a compiler:
54 | [1] Microsoft Visual C/C++ version 7.1 in C:\Program Files\Microsoft Visual Studio
55 | [0] None
56 | Compiler: 1
57 | Please verify your choices:
58 | Compiler: Microsoft Visual C/C++ 7.1
59 | Location: C:\Program Files\Microsoft Visual Studio
60 | Are these correct?([y]/n): y
61 |
62 | matlab> make
63 |
64 |
65 | For list of supported/compatible compilers for MATLAB, please check the
66 | following page:
67 |
68 | http://www.mathworks.com/support/compilers/current_release/
69 |
70 | Usage
71 | =====
72 |
73 | matlab> model = svmtrain(training_label_vector, training_instance_matrix [, 'libsvm_options']);
74 |
75 | -training_label_vector:
76 | An m by 1 vector of training labels (type must be double).
77 | -training_instance_matrix:
78 | An m by n matrix of m training instances with n features.
79 | It can be dense or sparse (type must be double).
80 | -libsvm_options:
81 | A string of training options in the same format as that of LIBSVM.
82 |
83 | matlab> [predicted_label, accuracy, decision_values/prob_estimates] = svmpredict(testing_label_vector, testing_instance_matrix, model [, 'libsvm_options']);
84 |
85 | -testing_label_vector:
86 | An m by 1 vector of prediction labels. If labels of test
87 | data are unknown, simply use any random values. (type must be double)
88 | -testing_instance_matrix:
89 | An m by n matrix of m testing instances with n features.
90 | It can be dense or sparse. (type must be double)
91 | -model:
92 | The output of svmtrain.
93 | -libsvm_options:
94 | A string of testing options in the same format as that of LIBSVM.
95 |
96 | Returned Model Structure
97 | ========================
98 |
99 | The 'svmtrain' function returns a model which can be used for future
100 | prediction. It is a structure and is organized as [Parameters, nr_class,
101 | totalSV, rho, Label, ProbA, ProbB, nSV, sv_coef, SVs]:
102 |
103 | -Parameters: parameters
104 | -nr_class: number of classes; = 2 for regression/one-class svm
105 | -totalSV: total #SV
106 | -rho: -b of the decision function(s) wx+b
107 | -Label: label of each class; empty for regression/one-class SVM
108 | -ProbA: pairwise probability information; empty if -b 0 or in one-class SVM
109 | -ProbB: pairwise probability information; empty if -b 0 or in one-class SVM
110 | -nSV: number of SVs for each class; empty for regression/one-class SVM
111 | -sv_coef: coefficients for SVs in decision functions
112 | -SVs: support vectors
113 |
114 | If you do not use the option '-b 1', ProbA and ProbB are empty
115 | matrices. If the '-v' option is specified, cross validation is
116 | conducted and the returned model is just a scalar: cross-validation
117 | accuracy for classification and mean-squared error for regression.
118 |
119 | More details about this model can be found in LIBSVM FAQ
120 | (http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html) and LIBSVM
121 | implementation document
122 | (http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.pdf).
123 |
124 | Result of Prediction
125 | ====================
126 |
127 | The function 'svmpredict' has three outputs. The first one,
128 | predictd_label, is a vector of predicted labels. The second output,
129 | accuracy, is a vector including accuracy (for classification), mean
130 | squared error, and squared correlation coefficient (for regression).
131 | The third is a matrix containing decision values or probability
132 | estimates (if '-b 1' is specified). If k is the number of classes,
133 | for decision values, each row includes results of predicting
134 | k(k-1)/2 binary-class SVMs. For probabilities, each row contains k values
135 | indicating the probability that the testing instance is in each class.
136 | Note that the order of classes here is the same as 'Label' field
137 | in the model structure.
138 |
139 | Other Utilities
140 | ===============
141 |
142 | A matlab function libsvmread reads files in LIBSVM format:
143 |
144 | [label_vector, instance_matrix] = libsvmread('data.txt');
145 |
146 | Two outputs are labels and instances, which can then be used as inputs
147 | of svmtrain or svmpredict.
148 |
149 | A matlab function libsvmwrite writes Matlab matrix to a file in LIBSVM format:
150 |
151 | libsvmwrite('data.txt', label_vector, instance_matrix]
152 |
153 | The instance_matrix must be a sparse matrix. (type must be double)
154 | For 32bit and 64bit MATLAB on Windows, pre-built binary files are ready
155 | in the directory `..\windows', but in future releases, we will only
156 | include 64bit MATLAB binary files.
157 |
158 | These codes are prepared by Rong-En Fan and Kai-Wei Chang from National
159 | Taiwan University.
160 |
161 | Examples
162 | ========
163 |
164 | Train and test on the provided data heart_scale:
165 |
166 | matlab> [heart_scale_label, heart_scale_inst] = libsvmread('../heart_scale');
167 | matlab> model = svmtrain(heart_scale_label, heart_scale_inst, '-c 1 -g 0.07');
168 | matlab> [predict_label, accuracy, dec_values] = svmpredict(heart_scale_label, heart_scale_inst, model); % test the training data
169 |
170 | For probability estimates, you need '-b 1' for training and testing:
171 |
172 | matlab> [heart_scale_label, heart_scale_inst] = libsvmread('../heart_scale');
173 | matlab> model = svmtrain(heart_scale_label, heart_scale_inst, '-c 1 -g 0.07 -b 1');
174 | matlab> [heart_scale_label, heart_scale_inst] = libsvmread('../heart_scale');
175 | matlab> [predict_label, accuracy, prob_estimates] = svmpredict(heart_scale_label, heart_scale_inst, model, '-b 1');
176 |
177 | To use precomputed kernel, you must include sample serial number as
178 | the first column of the training and testing data (assume your kernel
179 | matrix is K, # of instances is n):
180 |
181 | matlab> K1 = [(1:n)', K]; % include sample serial number as first column
182 | matlab> model = svmtrain(label_vector, K1, '-t 4');
183 | matlab> [predict_label, accuracy, dec_values] = svmpredict(label_vector, K1, model); % test the training data
184 |
185 | We give the following detailed example by splitting heart_scale into
186 | 150 training and 120 testing data. Constructing a linear kernel
187 | matrix and then using the precomputed kernel gives exactly the same
188 | testing error as using the LIBSVM built-in linear kernel.
189 |
190 | matlab> [heart_scale_label, heart_scale_inst] = libsvmread('../heart_scale');
191 | matlab>
192 | matlab> % Split Data
193 | matlab> train_data = heart_scale_inst(1:150,:);
194 | matlab> train_label = heart_scale_label(1:150,:);
195 | matlab> test_data = heart_scale_inst(151:270,:);
196 | matlab> test_label = heart_scale_label(151:270,:);
197 | matlab>
198 | matlab> % Linear Kernel
199 | matlab> model_linear = svmtrain(train_label, train_data, '-t 0');
200 | matlab> [predict_label_L, accuracy_L, dec_values_L] = svmpredict(test_label, test_data, model_linear);
201 | matlab>
202 | matlab> % Precomputed Kernel
203 | matlab> model_precomputed = svmtrain(train_label, [(1:150)', train_data*train_data'], '-t 4');
204 | matlab> [predict_label_P, accuracy_P, dec_values_P] = svmpredict(test_label, [(1:120)', test_data*train_data'], model_precomputed);
205 | matlab>
206 | matlab> accuracy_L % Display the accuracy using linear kernel
207 | matlab> accuracy_P % Display the accuracy using precomputed kernel
208 |
209 | Note that for testing, you can put anything in the
210 | testing_label_vector. For more details of precomputed kernels, please
211 | read the section ``Precomputed Kernels'' in the README of the LIBSVM
212 | package.
213 |
214 | Additional Information
215 | ======================
216 |
217 | This interface was initially written by Jun-Cheng Chen, Kuan-Jen Peng,
218 | Chih-Yuan Yang and Chih-Huai Cheng from Department of Computer
219 | Science, National Taiwan University. The current version was prepared
220 | by Rong-En Fan and Ting-Fan Wu. If you find this tool useful, please
221 | cite LIBSVM as follows
222 |
223 | Chih-Chung Chang and Chih-Jen Lin, LIBSVM : a library for
224 | support vector machines, 2001. Software available at
225 | http://www.csie.ntu.edu.tw/~cjlin/libsvm
226 |
227 | For any question, please contact Chih-Jen Lin ,
228 | or check the FAQ page:
229 |
230 | http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html#/Q9:_MATLAB_interface
231 |
--------------------------------------------------------------------------------
/matlab/libsvmread.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "mex.h"
8 |
9 | #if MX_API_VER < 0x07030000
10 | typedef int mwIndex;
11 | #endif
12 | #ifndef max
13 | #define max(x,y) (((x)>(y))?(x):(y))
14 | #endif
15 | #ifndef min
16 | #define min(x,y) (((x)<(y))?(x):(y))
17 | #endif
18 |
19 | void exit_with_help()
20 | {
21 | mexPrintf(
22 | "Usage: [label_vector, instance_matrix] = libsvmread('filename');\n"
23 | );
24 | }
25 |
26 | static void fake_answer(mxArray *plhs[])
27 | {
28 | plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
29 | plhs[1] = mxCreateDoubleMatrix(0, 0, mxREAL);
30 | }
31 |
32 | static char *line;
33 | static int max_line_len;
34 |
35 | static char* readline(FILE *input)
36 | {
37 | int len;
38 |
39 | if(fgets(line,max_line_len,input) == NULL)
40 | return NULL;
41 |
42 | while(strrchr(line,'\n') == NULL)
43 | {
44 | max_line_len *= 2;
45 | line = (char *) realloc(line, max_line_len);
46 | len = (int) strlen(line);
47 | if(fgets(line+len,max_line_len-len,input) == NULL)
48 | break;
49 | }
50 | return line;
51 | }
52 |
53 | // read in a problem (in libsvm format)
54 | void read_problem(const char *filename, mxArray *plhs[])
55 | {
56 | int max_index, min_index, inst_max_index, i;
57 | long elements, k;
58 | FILE *fp = fopen(filename,"r");
59 | int l = 0;
60 | char *endptr;
61 | mwIndex *ir, *jc;
62 | double *labels, *samples;
63 |
64 | if(fp == NULL)
65 | {
66 | mexPrintf("can't open input file %s\n",filename);
67 | fake_answer(plhs);
68 | return;
69 | }
70 |
71 | max_line_len = 1024;
72 | line = (char *) malloc(max_line_len*sizeof(char));
73 |
74 | max_index = 0;
75 | min_index = 1; // our index starts from 1
76 | elements = 0;
77 | while(readline(fp) != NULL)
78 | {
79 | char *idx, *val;
80 | // features
81 | int index = 0;
82 |
83 | inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has start from 0
84 | strtok(line," \t"); // label
85 | while (1)
86 | {
87 | idx = strtok(NULL,":"); // index:value
88 | val = strtok(NULL," \t");
89 | if(val == NULL)
90 | break;
91 |
92 | errno = 0;
93 | index = (int) strtol(idx,&endptr,10);
94 | if(endptr == idx || errno != 0 || *endptr != '\0' || index <= inst_max_index)
95 | {
96 | mexPrintf("Wrong input format at line %d\n",l+1);
97 | fake_answer(plhs);
98 | return;
99 | }
100 | else
101 | inst_max_index = index;
102 |
103 | min_index = min(min_index, index);
104 | elements++;
105 | }
106 | max_index = max(max_index, inst_max_index);
107 | l++;
108 | }
109 | rewind(fp);
110 |
111 | // y
112 | plhs[0] = mxCreateDoubleMatrix(l, 1, mxREAL);
113 | // x^T
114 | if (min_index <= 0)
115 | plhs[1] = mxCreateSparse(max_index-min_index+1, l, elements, mxREAL);
116 | else
117 | plhs[1] = mxCreateSparse(max_index, l, elements, mxREAL);
118 |
119 | labels = mxGetPr(plhs[0]);
120 | samples = mxGetPr(plhs[1]);
121 | ir = mxGetIr(plhs[1]);
122 | jc = mxGetJc(plhs[1]);
123 |
124 | k=0;
125 | for(i=0;i start from 0
156 |
157 | errno = 0;
158 | samples[k] = strtod(val,&endptr);
159 | if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
160 | {
161 | mexPrintf("Wrong input format at line %d\n",i+1);
162 | fake_answer(plhs);
163 | return;
164 | }
165 | ++k;
166 | }
167 | }
168 | jc[l] = k;
169 |
170 | fclose(fp);
171 | free(line);
172 |
173 | {
174 | mxArray *rhs[1], *lhs[1];
175 | rhs[0] = plhs[1];
176 | if(mexCallMATLAB(1, lhs, 1, rhs, "transpose"))
177 | {
178 | mexPrintf("Error: cannot transpose problem\n");
179 | fake_answer(plhs);
180 | return;
181 | }
182 | plhs[1] = lhs[0];
183 | }
184 | }
185 |
186 | void mexFunction( int nlhs, mxArray *plhs[],
187 | int nrhs, const mxArray *prhs[] )
188 | {
189 | if(nrhs == 1)
190 | {
191 | char filename[256];
192 |
193 | mxGetString(prhs[0], filename, mxGetN(prhs[0]) + 1);
194 |
195 | if(filename == NULL)
196 | {
197 | mexPrintf("Error: filename is NULL\n");
198 | return;
199 | }
200 |
201 | read_problem(filename, plhs);
202 | }
203 | else
204 | {
205 | exit_with_help();
206 | fake_answer(plhs);
207 | return;
208 | }
209 | }
210 |
211 |
--------------------------------------------------------------------------------
/matlab/libsvmwrite.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "mex.h"
5 |
6 | #if MX_API_VER < 0x07030000
7 | typedef int mwIndex;
8 | #endif
9 |
10 | void exit_with_help()
11 | {
12 | mexPrintf(
13 | "Usage: libsvmwrite('filename', label_vector, instance_matrix);\n"
14 | );
15 | }
16 |
17 | void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *instance_mat)
18 | {
19 | FILE *fp = fopen(filename,"w");
20 | int i, k, low, high, l;
21 | mwIndex *ir, *jc;
22 | int label_vector_row_num;
23 | double *samples, *labels;
24 | mxArray *instance_mat_col; // instance sparse matrix in column format
25 |
26 | if(fp ==NULL)
27 | {
28 | mexPrintf("can't open output file %s\n",filename);
29 | return;
30 | }
31 |
32 | // transpose instance matrix
33 | {
34 | mxArray *prhs[1], *plhs[1];
35 | prhs[0] = mxDuplicateArray(instance_mat);
36 | if(mexCallMATLAB(1, plhs, 1, prhs, "transpose"))
37 | {
38 | mexPrintf("Error: cannot transpose instance matrix\n");
39 | return;
40 | }
41 | instance_mat_col = plhs[0];
42 | mxDestroyArray(prhs[0]);
43 | }
44 |
45 | // the number of instance
46 | l = (int) mxGetN(instance_mat_col);
47 | label_vector_row_num = (int) mxGetM(label_vec);
48 |
49 | if(label_vector_row_num!=l)
50 | {
51 | mexPrintf("Length of label vector does not match # of instances.\n");
52 | return;
53 | }
54 |
55 | // each column is one instance
56 | labels = mxGetPr(label_vec);
57 | samples = mxGetPr(instance_mat_col);
58 | ir = mxGetIr(instance_mat_col);
59 | jc = mxGetJc(instance_mat_col);
60 |
61 | for(i=0;i
2 | #include
3 | #include "svm.h"
4 |
5 | #include "mex.h"
6 |
7 | #if MX_API_VER < 0x07030000
8 | typedef int mwIndex;
9 | #endif
10 |
11 | #define NUM_OF_RETURN_FIELD 10
12 |
13 | #define Malloc(type,n) (type *)malloc((n)*sizeof(type))
14 |
15 | static const char *field_names[] = {
16 | "Parameters",
17 | "nr_class",
18 | "totalSV",
19 | "rho",
20 | "Label",
21 | "ProbA",
22 | "ProbB",
23 | "nSV",
24 | "sv_coef",
25 | "SVs"
26 | };
27 |
28 | const char *model_to_matlab_structure(mxArray *plhs[], int num_of_feature, struct svm_model *model)
29 | {
30 | int i, j, n;
31 | double *ptr;
32 | mxArray *return_model, **rhs;
33 | int out_id = 0;
34 |
35 | rhs = (mxArray **)mxMalloc(sizeof(mxArray *)*NUM_OF_RETURN_FIELD);
36 |
37 | // Parameters
38 | rhs[out_id] = mxCreateDoubleMatrix(5, 1, mxREAL);
39 | ptr = mxGetPr(rhs[out_id]);
40 | ptr[0] = model->param.svm_type;
41 | ptr[1] = model->param.kernel_type;
42 | ptr[2] = model->param.degree;
43 | ptr[3] = model->param.gamma;
44 | ptr[4] = model->param.coef0;
45 | out_id++;
46 |
47 | // nr_class
48 | rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
49 | ptr = mxGetPr(rhs[out_id]);
50 | ptr[0] = model->nr_class;
51 | out_id++;
52 |
53 | // total SV
54 | rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
55 | ptr = mxGetPr(rhs[out_id]);
56 | ptr[0] = model->l;
57 | out_id++;
58 |
59 | // rho
60 | n = model->nr_class*(model->nr_class-1)/2;
61 | rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
62 | ptr = mxGetPr(rhs[out_id]);
63 | for(i = 0; i < n; i++)
64 | ptr[i] = model->rho[i];
65 | out_id++;
66 |
67 | // Label
68 | if(model->label)
69 | {
70 | rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL);
71 | ptr = mxGetPr(rhs[out_id]);
72 | for(i = 0; i < model->nr_class; i++)
73 | ptr[i] = model->label[i];
74 | }
75 | else
76 | rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
77 | out_id++;
78 |
79 | // probA
80 | if(model->probA != NULL)
81 | {
82 | rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
83 | ptr = mxGetPr(rhs[out_id]);
84 | for(i = 0; i < n; i++)
85 | ptr[i] = model->probA[i];
86 | }
87 | else
88 | rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
89 | out_id ++;
90 |
91 | // probB
92 | if(model->probB != NULL)
93 | {
94 | rhs[out_id] = mxCreateDoubleMatrix(n, 1, mxREAL);
95 | ptr = mxGetPr(rhs[out_id]);
96 | for(i = 0; i < n; i++)
97 | ptr[i] = model->probB[i];
98 | }
99 | else
100 | rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
101 | out_id++;
102 |
103 | // nSV
104 | if(model->nSV)
105 | {
106 | rhs[out_id] = mxCreateDoubleMatrix(model->nr_class, 1, mxREAL);
107 | ptr = mxGetPr(rhs[out_id]);
108 | for(i = 0; i < model->nr_class; i++)
109 | ptr[i] = model->nSV[i];
110 | }
111 | else
112 | rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
113 | out_id++;
114 |
115 | // sv_coef
116 | rhs[out_id] = mxCreateDoubleMatrix(model->l, model->nr_class-1, mxREAL);
117 | ptr = mxGetPr(rhs[out_id]);
118 | for(i = 0; i < model->nr_class-1; i++)
119 | for(j = 0; j < model->l; j++)
120 | ptr[(i*(model->l))+j] = model->sv_coef[i][j];
121 | out_id++;
122 |
123 | // SVs
124 | {
125 | int ir_index, nonzero_element;
126 | mwIndex *ir, *jc;
127 | mxArray *pprhs[1], *pplhs[1];
128 |
129 | if(model->param.kernel_type == PRECOMPUTED)
130 | {
131 | nonzero_element = model->l;
132 | num_of_feature = 1;
133 | }
134 | else
135 | {
136 | nonzero_element = 0;
137 | for(i = 0; i < model->l; i++) {
138 | j = 0;
139 | while(model->SV[i][j].index != -1)
140 | {
141 | nonzero_element++;
142 | j++;
143 | }
144 | }
145 | }
146 |
147 | // SV in column, easier accessing
148 | rhs[out_id] = mxCreateSparse(num_of_feature, model->l, nonzero_element, mxREAL);
149 | ir = mxGetIr(rhs[out_id]);
150 | jc = mxGetJc(rhs[out_id]);
151 | ptr = mxGetPr(rhs[out_id]);
152 | jc[0] = ir_index = 0;
153 | for(i = 0;i < model->l; i++)
154 | {
155 | if(model->param.kernel_type == PRECOMPUTED)
156 | {
157 | // make a (1 x model->l) matrix
158 | ir[ir_index] = 0;
159 | ptr[ir_index] = model->SV[i][0].value;
160 | ir_index++;
161 | jc[i+1] = jc[i] + 1;
162 | }
163 | else
164 | {
165 | int x_index = 0;
166 | while (model->SV[i][x_index].index != -1)
167 | {
168 | ir[ir_index] = model->SV[i][x_index].index - 1;
169 | ptr[ir_index] = model->SV[i][x_index].value;
170 | ir_index++, x_index++;
171 | }
172 | jc[i+1] = jc[i] + x_index;
173 | }
174 | }
175 | // transpose back to SV in row
176 | pprhs[0] = rhs[out_id];
177 | if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose"))
178 | return "cannot transpose SV matrix";
179 | rhs[out_id] = pplhs[0];
180 | out_id++;
181 | }
182 |
183 | /* Create a struct matrix contains NUM_OF_RETURN_FIELD fields */
184 | return_model = mxCreateStructMatrix(1, 1, NUM_OF_RETURN_FIELD, field_names);
185 |
186 | /* Fill struct matrix with input arguments */
187 | for(i = 0; i < NUM_OF_RETURN_FIELD; i++)
188 | mxSetField(return_model,0,field_names[i],mxDuplicateArray(rhs[i]));
189 | /* return */
190 | plhs[0] = return_model;
191 | mxFree(rhs);
192 |
193 | return NULL;
194 | }
195 |
196 | struct svm_model *matlab_matrix_to_model(const mxArray *matlab_struct, const char **msg)
197 | {
198 | int i, j, n, num_of_fields;
199 | double *ptr;
200 | int id = 0;
201 | struct svm_node *x_space;
202 | struct svm_model *model;
203 | mxArray **rhs;
204 |
205 | num_of_fields = mxGetNumberOfFields(matlab_struct);
206 | if(num_of_fields != NUM_OF_RETURN_FIELD)
207 | {
208 | *msg = "number of return field is not correct";
209 | return NULL;
210 | }
211 | rhs = (mxArray **) mxMalloc(sizeof(mxArray *)*num_of_fields);
212 |
213 | for(i=0;irho = NULL;
218 | model->probA = NULL;
219 | model->probB = NULL;
220 | model->label = NULL;
221 | model->nSV = NULL;
222 | model->free_sv = 1; // XXX
223 |
224 | ptr = mxGetPr(rhs[id]);
225 | model->param.svm_type = (int)ptr[0];
226 | model->param.kernel_type = (int)ptr[1];
227 | model->param.degree = (int)ptr[2];
228 | model->param.gamma = ptr[3];
229 | model->param.coef0 = ptr[4];
230 | id++;
231 |
232 | ptr = mxGetPr(rhs[id]);
233 | model->nr_class = (int)ptr[0];
234 | id++;
235 |
236 | ptr = mxGetPr(rhs[id]);
237 | model->l = (int)ptr[0];
238 | id++;
239 |
240 | // rho
241 | n = model->nr_class * (model->nr_class-1)/2;
242 | model->rho = (double*) malloc(n*sizeof(double));
243 | ptr = mxGetPr(rhs[id]);
244 | for(i=0;irho[i] = ptr[i];
246 | id++;
247 |
248 | // label
249 | if(mxIsEmpty(rhs[id]) == 0)
250 | {
251 | model->label = (int*) malloc(model->nr_class*sizeof(int));
252 | ptr = mxGetPr(rhs[id]);
253 | for(i=0;inr_class;i++)
254 | model->label[i] = (int)ptr[i];
255 | }
256 | id++;
257 |
258 | // probA
259 | if(mxIsEmpty(rhs[id]) == 0)
260 | {
261 | model->probA = (double*) malloc(n*sizeof(double));
262 | ptr = mxGetPr(rhs[id]);
263 | for(i=0;iprobA[i] = ptr[i];
265 | }
266 | id++;
267 |
268 | // probB
269 | if(mxIsEmpty(rhs[id]) == 0)
270 | {
271 | model->probB = (double*) malloc(n*sizeof(double));
272 | ptr = mxGetPr(rhs[id]);
273 | for(i=0;iprobB[i] = ptr[i];
275 | }
276 | id++;
277 |
278 | // nSV
279 | if(mxIsEmpty(rhs[id]) == 0)
280 | {
281 | model->nSV = (int*) malloc(model->nr_class*sizeof(int));
282 | ptr = mxGetPr(rhs[id]);
283 | for(i=0;inr_class;i++)
284 | model->nSV[i] = (int)ptr[i];
285 | }
286 | id++;
287 |
288 | // sv_coef
289 | ptr = mxGetPr(rhs[id]);
290 | model->sv_coef = (double**) malloc((model->nr_class-1)*sizeof(double));
291 | for( i=0 ; i< model->nr_class -1 ; i++ )
292 | model->sv_coef[i] = (double*) malloc((model->l)*sizeof(double));
293 | for(i = 0; i < model->nr_class - 1; i++)
294 | for(j = 0; j < model->l; j++)
295 | model->sv_coef[i][j] = ptr[i*(model->l)+j];
296 | id++;
297 |
298 | // SV
299 | {
300 | int sr, sc, elements;
301 | int num_samples;
302 | mwIndex *ir, *jc;
303 | mxArray *pprhs[1], *pplhs[1];
304 |
305 | // transpose SV
306 | pprhs[0] = rhs[id];
307 | if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose"))
308 | {
309 | svm_free_and_destroy_model(&model);
310 | *msg = "cannot transpose SV matrix";
311 | return NULL;
312 | }
313 | rhs[id] = pplhs[0];
314 |
315 | sr = (int)mxGetN(rhs[id]);
316 | sc = (int)mxGetM(rhs[id]);
317 |
318 | ptr = mxGetPr(rhs[id]);
319 | ir = mxGetIr(rhs[id]);
320 | jc = mxGetJc(rhs[id]);
321 |
322 | num_samples = (int)mxGetNzmax(rhs[id]);
323 |
324 | elements = num_samples + sr;
325 |
326 | model->SV = (struct svm_node **) malloc(sr * sizeof(struct svm_node *));
327 | x_space = (struct svm_node *)malloc(elements * sizeof(struct svm_node));
328 |
329 | // SV is in column
330 | for(i=0;iSV[i] = &x_space[low+i];
335 | for(j=low;jSV[i][x_index].index = (int)ir[j] + 1;
338 | model->SV[i][x_index].value = ptr[j];
339 | x_index++;
340 | }
341 | model->SV[i][x_index].index = -1;
342 | }
343 |
344 | id++;
345 | }
346 | mxFree(rhs);
347 |
348 | return model;
349 | }
350 |
--------------------------------------------------------------------------------
/matlab/svm_model_matlab.h:
--------------------------------------------------------------------------------
1 | const char *model_to_matlab_structure(mxArray *plhs[], int num_of_feature, struct svm_model *model);
2 | struct svm_model *matlab_matrix_to_model(const mxArray *matlab_struct, const char **error_message);
3 |
--------------------------------------------------------------------------------
/matlab/svmpredict.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "svm.h"
5 |
6 | #include "mex.h"
7 | #include "svm_model_matlab.h"
8 |
9 | #if MX_API_VER < 0x07030000
10 | typedef int mwIndex;
11 | #endif
12 |
13 | #define CMD_LEN 2048
14 |
15 | void read_sparse_instance(const mxArray *prhs, int index, struct svm_node *x)
16 | {
17 | int i, j, low, high;
18 | mwIndex *ir, *jc;
19 | double *samples;
20 |
21 | ir = mxGetIr(prhs);
22 | jc = mxGetJc(prhs);
23 | samples = mxGetPr(prhs);
24 |
25 | // each column is one instance
26 | j = 0;
27 | low = (int)jc[index], high = (int)jc[index+1];
28 | for(i=low;iparam.kernel_type == PRECOMPUTED)
89 | {
90 | // precomputed kernel requires dense matrix, so we make one
91 | mxArray *rhs[1], *lhs[1];
92 | rhs[0] = mxDuplicateArray(prhs[1]);
93 | if(mexCallMATLAB(1, lhs, 1, rhs, "full"))
94 | {
95 | mexPrintf("Error: cannot full testing instance matrix\n");
96 | fake_answer(plhs);
97 | return;
98 | }
99 | ptr_instance = mxGetPr(lhs[0]);
100 | mxDestroyArray(rhs[0]);
101 | }
102 | else
103 | {
104 | mxArray *pprhs[1];
105 | pprhs[0] = mxDuplicateArray(prhs[1]);
106 | if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose"))
107 | {
108 | mexPrintf("Error: cannot transpose testing instance matrix\n");
109 | fake_answer(plhs);
110 | return;
111 | }
112 | }
113 | }
114 |
115 | if(predict_probability)
116 | {
117 | if(svm_type==NU_SVR || svm_type==EPSILON_SVR)
118 | mexPrintf("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g\n",svm_get_svr_probability(model));
119 | else
120 | prob_estimates = (double *) malloc(nr_class*sizeof(double));
121 | }
122 |
123 | plhs[0] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL);
124 | if(predict_probability)
125 | {
126 | // prob estimates are in plhs[2]
127 | if(svm_type==C_SVC || svm_type==NU_SVC)
128 | plhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class, mxREAL);
129 | else
130 | plhs[2] = mxCreateDoubleMatrix(0, 0, mxREAL);
131 | }
132 | else
133 | {
134 | // decision values are in plhs[2]
135 | if(svm_type == ONE_CLASS ||
136 | svm_type == EPSILON_SVR ||
137 | svm_type == NU_SVR)
138 | plhs[2] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL);
139 | else
140 | plhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class*(nr_class-1)/2, mxREAL);
141 | }
142 |
143 | ptr_predict_label = mxGetPr(plhs[0]);
144 | ptr_prob_estimates = mxGetPr(plhs[2]);
145 | ptr_dec_values = mxGetPr(plhs[2]);
146 | x = (struct svm_node*)malloc((feature_number+1)*sizeof(struct svm_node) );
147 | for(instance_index=0;instance_indexparam.kernel_type != PRECOMPUTED) // prhs[1]^T is still sparse
155 | read_sparse_instance(pplhs[0], instance_index, x);
156 | else
157 | {
158 | for(i=0;i 4 || nrhs < 3)
257 | {
258 | exit_with_help();
259 | fake_answer(plhs);
260 | return;
261 | }
262 |
263 | if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1])) {
264 | mexPrintf("Error: label vector and instance matrix must be double\n");
265 | fake_answer(plhs);
266 | return;
267 | }
268 |
269 | if(mxIsStruct(prhs[2]))
270 | {
271 | const char *error_msg;
272 |
273 | // parse options
274 | if(nrhs==4)
275 | {
276 | int i, argc = 1;
277 | char cmd[CMD_LEN], *argv[CMD_LEN/2];
278 |
279 | // put options in argv[]
280 | mxGetString(prhs[3], cmd, mxGetN(prhs[3]) + 1);
281 | if((argv[argc] = strtok(cmd, " ")) != NULL)
282 | while((argv[++argc] = strtok(NULL, " ")) != NULL)
283 | ;
284 |
285 | for(i=1;i=argc)
289 | {
290 | exit_with_help();
291 | fake_answer(plhs);
292 | return;
293 | }
294 | switch(argv[i-1][1])
295 | {
296 | case 'b':
297 | prob_estimate_flag = atoi(argv[i]);
298 | break;
299 | default:
300 | mexPrintf("Unknown option: -%c\n", argv[i-1][1]);
301 | exit_with_help();
302 | fake_answer(plhs);
303 | return;
304 | }
305 | }
306 | }
307 |
308 | model = matlab_matrix_to_model(prhs[2], &error_msg);
309 | if (model == NULL)
310 | {
311 | mexPrintf("Error: can't read model: %s\n", error_msg);
312 | fake_answer(plhs);
313 | return;
314 | }
315 |
316 | if(prob_estimate_flag)
317 | {
318 | if(svm_check_probability_model(model)==0)
319 | {
320 | mexPrintf("Model does not support probabiliy estimates\n");
321 | fake_answer(plhs);
322 | svm_free_and_destroy_model(&model);
323 | return;
324 | }
325 | }
326 | else
327 | {
328 | if(svm_check_probability_model(model)!=0)
329 | mexPrintf("Model supports probability estimates, but disabled in predicton.\n");
330 | }
331 |
332 | predict(plhs, prhs, model, prob_estimate_flag);
333 | // destroy model
334 | svm_free_and_destroy_model(&model);
335 | }
336 | else
337 | {
338 | mexPrintf("model file should be a struct array\n");
339 | fake_answer(plhs);
340 | }
341 |
342 | return;
343 | }
344 |
--------------------------------------------------------------------------------
/python/Makefile:
--------------------------------------------------------------------------------
1 | all = lib
2 |
3 | lib:
4 | cd ..; make lib; cd -
5 |
--------------------------------------------------------------------------------
/python/README:
--------------------------------------------------------------------------------
1 | ----------------------------------
2 | --- Python interface of LIBSVM ---
3 | ----------------------------------
4 |
5 | Table of Contents
6 | =================
7 |
8 | - Introduction
9 | - Installation
10 | - Quick Start
11 | - Design Description
12 | - Data Structures
13 | - Utility Functions
14 | - Additional Information
15 |
16 | Introduction
17 | ============
18 |
19 | Python (http://www.python.org/) is a programming language suitable for rapid
20 | development. This tool provides a simple Python interface to LIBSVM, a library
21 | for support vector machines (http://www.csie.ntu.edu.tw/~cjlin/libsvm). The
22 | interface is very easy to use as the usage is the same as that of LIBSVM. The
23 | interface is developed with the built-in Python library "ctypes."
24 |
25 | Installation
26 | ============
27 |
28 | On Unix systems, type
29 |
30 | > make
31 |
32 | The interface needs only LIBSVM shared library, which is generated by
33 | the above command. We assume that the shared library is on the LIBSVM
34 | main directory or in the system path.
35 |
36 | For windows, the shared library libsvm.dll is ready in the directory
37 | `..\windows'. You can also copy it to the system directory (e.g.,
38 | `C:\WINDOWS\system32\' for Windows XP). To regenerate the shared library,
39 | please follow the instruction of building windows binaries in LIBSVM README.
40 |
41 | Quick Start
42 | ===========
43 |
44 | There are two levels of usage. The high-level one uses utility functions
45 | in svmutil.py and the usage is the same as the LIBSVM MATLAB interface.
46 |
47 | >>> from svmutil import *
48 | # Read data in LIBSVM format
49 | >>> y, x = svm_read_problem('../heart_scale')
50 | >>> m = svm_train(y[:200], x[:200], '-c 4')
51 | >>> p_label, p_acc, p_val = svm_predict(y[200:], x[200:], m)
52 |
53 | # Construct problem in python format
54 | # Dense data
55 | >>> y, x = [1,-1], [[1,0,1], [-1,0,-1]]
56 | # Sparse data
57 | >>> y, x = [1,-1], [{1:1, 3:1}, {1:-1,3:-1}]
58 | >>> prob = svm_problem(y, x)
59 | >>> param = svm_parameter('-c 4 -b 1')
60 | >>> m = svm_train(prob, param)
61 |
62 | # Other utility functions
63 | >>> svm_save_model('heart_scale.model', m)
64 | >>> m = svm_load_model('heart_scale.model')
65 | >>> p_label, p_acc, p_val = svm_predict(y, x, m, '-b 1')
66 | >>> ACC, MSE, SCC = evaluations(y, p_val)
67 |
68 | # Getting online help
69 | >>> help(svm_train)
70 |
71 | The low-level use directly calls C interfaces imported by svm.py. Note that
72 | all arguments and return values are in ctypes format. You need to handle them
73 | carefully.
74 |
75 | >>> from svm import *
76 | >>> prob = svm_problem([1,-1], [{1:1, 3:1}, {1:-1,3:-1}])
77 | >>> param = svm_parameter('-c 4')
78 | >>> m = libsvm.svm_train(prob, param) # m is a ctype pointer to an svm_model
79 | # Convert a Python-format instance to svm_nodearray, a ctypes structure
80 | >>> x0, max_idx = gen_svm_nodearray({1:1, 3:1})
81 | >>> label = libsvm.svm_predict(m, x0)
82 |
83 | Design Description
84 | ==================
85 |
86 | There are two files svm.py and svmutil.py, which respectively correspond to
87 | low-level and high-level use of the interface.
88 |
89 | In svm.py, we adopt the Python built-in library "ctypes," so that
90 | Python can directly access C structures and interface functions defined
91 | in svm.h.
92 |
93 | While advanced users can use structures/functions in svm.py, to
94 | avoid handling ctypes structures, in svmutil.py we provide some easy-to-use
95 | functions. The usage is similar to LIBSVM MATLAB interface.
96 |
97 | Data Structures
98 | ===============
99 |
100 | Four data structures derived from svm.h are svm_node, svm_problem, svm_parameter,
101 | and svm_model. They all contain fields with the same names in svm.h. Access
102 | these fields carefully because you directly use a C structure instead of a
103 | Python object. For svm_model, accessing the field directly is not recommanded.
104 | Programmers should use the interface functions or methods of svm_model class
105 | in Python to get the values. The following description introduces additional
106 | fields and methods.
107 |
108 | Before using the data structures, execute the following command to load the
109 | LIBSVM shared library:
110 |
111 | >>> from svm import *
112 |
113 | - class svm_node:
114 |
115 | Construct an svm_node.
116 |
117 | >>> node = svm_node(idx, val)
118 |
119 | idx: an integer indicates the feature index.
120 |
121 | val: a float indicates the feature value.
122 |
123 | - Function: gen_svm_nodearray(xi [,feature_max=None [,issparse=False]])
124 |
125 | Generate a feature vector from a Python list/tuple or a dictionary:
126 |
127 | >>> xi, max_idx = gen_svm_nodearray({1:1, 3:1, 5:-2})
128 |
129 | xi: the returned svm_nodearray (a ctypes structure)
130 |
131 | max_idx: the maximal feature index of xi
132 |
133 | issparse: if issparse == True, zero feature values are removed. The default
134 | value is False for supporting the pre-computed kernel.
135 |
136 | feature_max: if feature_max is assigned, features with indices larger than
137 | feature_max are removed.
138 |
139 | - class svm_problem:
140 |
141 | Construct an svm_problem instance
142 |
143 | >>> prob = svm_problem(y, x)
144 |
145 | y: a Python list/tuple of l labels (type must be int/double).
146 |
147 | x: a Python list/tuple of l data instances. Each element of x must be
148 | an instance of list/tuple/dictionary type.
149 |
150 | Note that if your x contains sparse data (i.e., dictionary), the internal
151 | ctypes data format is still sparse.
152 |
153 | - class svm_parameter:
154 |
155 | Construct an svm_parameter instance
156 |
157 | >>> param = svm_parameter('training_options')
158 |
159 | If 'training_options' is empty, LIBSVM default values are applied.
160 |
161 | Set param to LIBSVM default values.
162 |
163 | >>> param.set_to_default_values()
164 |
165 | Parse a string of options.
166 |
167 | >>> param.parse_options('training_options')
168 |
169 | Show values of parameters.
170 |
171 | >>> param.show()
172 |
173 | - class svm_model:
174 |
175 | There are two ways to obtain an instance of svm_model:
176 |
177 | >>> model = svm_train(y, x)
178 | >>> model = svm_load_model('model_file_name')
179 |
180 | Note that the returned structure of interface functions
181 | libsvm.svm_train and libsvm.svm_load_model is a ctypes pointer of
182 | svm_model, which is different from the svm_model object returned
183 | by svm_train and svm_load_model in svmutil.py. We provide a
184 | function toPyModel for the conversion:
185 |
186 | >>> model_ptr = libsvm.svm_train(prob, param)
187 | >>> model = toPyModel(model_ptr)
188 |
189 | If you obtain a model in a way other than the above approaches,
190 | handle it carefully to avoid memory leak or segmentation fault.
191 |
192 | Some interface functions to access LIBSVM models are wrapped as
193 | members of the class svm_model:
194 |
195 | >>> svm_type = model.get_svm_type()
196 | >>> nr_class = model.get_nr_class()
197 | >>> svr_probability = model.get_svr_probability()
198 | >>> class_labels = model.get_labels()
199 | >>> is_prob_model = model.is_probability_model()
200 | >>> support_vector_coefficients = model.get_sv_coef()
201 | >>> support_vectors = model.get_SV()
202 |
203 | Utility Functions
204 | =================
205 |
206 | To use utility functions, type
207 |
208 | >>> from svmutil import *
209 |
210 | The above command loads
211 | svm_train() : train an SVM model
212 | svm_predict() : predict testing data
213 | svm_read_problem() : read the data from a LIBSVM-format file.
214 | svm_load_model() : load a LIBSVM model.
215 | svm_save_model() : save model to a file.
216 | evaluations() : evaluate prediction results.
217 |
218 | - Function: svm_train
219 |
220 | There are three ways to call svm_train()
221 |
222 | >>> model = svm_train(y, x [, 'training_options'])
223 | >>> model = svm_train(prob [, 'training_options'])
224 | >>> model = svm_train(prob, param)
225 |
226 | y: a list/tuple of l training labels (type must be int/double).
227 |
228 | x: a list/tuple of l training instances. The feature vector of
229 | each training instance is an instance of list/tuple or dictionary.
230 |
231 | training_options: a string in the same form as that for LIBSVM command
232 | mode.
233 |
234 | prob: an svm_problem instance generated by calling
235 | svm_problem(y, x).
236 |
237 | param: an svm_parameter instance generated by calling
238 | svm_parameter('training_options')
239 |
240 | model: the returned svm_model instance. See svm.h for details of this
241 | structure. If '-v' is specified, cross validation is
242 | conducted and the returned model is just a scalar: cross-validation
243 | accuracy for classification and mean-squared error for regression.
244 |
245 | To train the same data many times with different
246 | parameters, the second and the third ways should be faster..
247 |
248 | Examples:
249 |
250 | >>> y, x = svm_read_problem('../heart_scale')
251 | >>> prob = svm_problem(y, x)
252 | >>> param = svm_parameter('-s 3 -c 5 -h 0')
253 | >>> m = svm_train(y, x, '-c 5')
254 | >>> m = svm_train(prob, '-t 2 -c 5')
255 | >>> m = svm_train(prob, param)
256 | >>> CV_ACC = svm_train(y, x, '-v 3')
257 |
258 | - Function: svm_predict
259 |
260 | To predict testing data with a model, use
261 |
262 | >>> p_labs, p_acc, p_vals = svm_predict(y, x, model [,'predicting_options'])
263 |
264 | y: a list/tuple of l true labels (type must be int/double). It is used
265 | for calculating the accuracy. Use [0]*len(x) if true labels are
266 | unavailable.
267 |
268 | x: a list/tuple of l predicting instances. The feature vector of
269 | each predicting instance is an instance of list/tuple or dictionary.
270 |
271 | predicting_options: a string of predicting options in the same format as
272 | that of LIBSVM.
273 |
274 | model: an svm_model instance.
275 |
276 | p_labels: a list of predicted labels
277 |
278 | p_acc: a tuple including accuracy (for classification), mean
279 | squared error, and squared correlation coefficient (for
280 | regression).
281 |
282 | p_vals: a list of decision values or probability estimates (if '-b 1'
283 | is specified). If k is the number of classes, for decision values,
284 | each element includes results of predicting k(k-1)/2 binary-class
285 | SVMs. For probabilities, each element contains k values indicating
286 | the probability that the testing instance is in each class.
287 | Note that the order of classes is the same as the 'model.label'
288 | field in the model structure.
289 |
290 | Example:
291 |
292 | >>> m = svm_train(y, x, '-c 5')
293 | >>> p_labels, p_acc, p_vals = svm_predict(y, x, m)
294 |
295 | - Functions: svm_read_problem/svm_load_model/svm_save_model
296 |
297 | See the usage by examples:
298 |
299 | >>> y, x = svm_read_problem('data.txt')
300 | >>> m = svm_load_model('model_file')
301 | >>> svm_save_model('model_file', m)
302 |
303 | - Function: evaluations
304 |
305 | Calculate some evaluations using the true values (ty) and predicted
306 | values (pv):
307 |
308 | >>> (ACC, MSE, SCC) = evaluations(ty, pv)
309 |
310 | ty: a list of true values.
311 |
312 | pv: a list of predict values.
313 |
314 | ACC: accuracy.
315 |
316 | MSE: mean squared error.
317 |
318 | SCC: squared correlation coefficient.
319 |
320 |
321 | Additional Information
322 | ======================
323 |
324 | This interface was written by Hsiang-Fu Yu from Department of Computer
325 | Science, National Taiwan University. If you find this tool useful, please
326 | cite LIBSVM as follows
327 |
328 | Chih-Chung Chang and Chih-Jen Lin, LIBSVM : a library for
329 | support vector machines, 2001. Software available at
330 | http://www.csie.ntu.edu.tw/~cjlin/libsvm
331 |
332 | For any question, please contact Chih-Jen Lin ,
333 | or check the FAQ page:
334 |
335 | http://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html
336 |
--------------------------------------------------------------------------------
/python/svm.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from ctypes import *
4 | from ctypes.util import find_library
5 | import sys
6 | import os
7 |
8 | # For unix the prefix 'lib' is not considered.
9 | if find_library('svm'):
10 | libsvm = CDLL(find_library('svm'))
11 | elif find_library('libsvm'):
12 | libsvm = CDLL(find_library('libsvm'))
13 | else:
14 | if sys.platform == 'win32':
15 | libsvm = CDLL(os.path.join(os.path.dirname(__file__),\
16 | '../windows/libsvm.dll'))
17 | else:
18 | libsvm = CDLL(os.path.join(os.path.dirname(__file__),\
19 | '../libsvm.so.2'))
20 |
21 | # Construct constants
22 | SVM_TYPE = ['C_SVC', 'NU_SVC', 'ONE_CLASS', 'EPSILON_SVR', 'NU_SVR' ]
23 | KERNEL_TYPE = ['LINEAR', 'POLY', 'RBF', 'SIGMOID', 'PRECOMPUTED']
24 | for i, s in enumerate(SVM_TYPE): exec("%s = %d" % (s , i))
25 | for i, s in enumerate(KERNEL_TYPE): exec("%s = %d" % (s , i))
26 |
27 | PRINT_STRING_FUN = CFUNCTYPE(None, c_char_p)
28 | def print_null(s):
29 | return
30 |
31 | def genFields(names, types):
32 | return list(zip(names, types))
33 |
34 | def fillprototype(f, restype, argtypes):
35 | f.restype = restype
36 | f.argtypes = argtypes
37 |
38 | class svm_node(Structure):
39 | _names = ["index", "value"]
40 | _types = [c_int, c_double]
41 | _fields_ = genFields(_names, _types)
42 |
43 | def gen_svm_nodearray(xi, feature_max=None, issparse=None):
44 | if isinstance(xi, dict):
45 | index_range = xi.keys()
46 | elif isinstance(xi, (list, tuple)):
47 | index_range = range(len(xi))
48 | else:
49 | raise TypeError('xi should be a dictionary, list or tuple')
50 |
51 | if feature_max:
52 | assert(isinstance(feature_max, int))
53 | index_range = filter(lambda j: j <= feature_max, index_range)
54 | if issparse:
55 | index_range = filter(lambda j:xi[j] != 0, index_range)
56 |
57 | index_range = sorted(index_range)
58 | ret = (svm_node * (len(index_range)+1))()
59 | ret[-1].index = -1
60 | for idx, j in enumerate(index_range):
61 | ret[idx].index = j
62 | ret[idx].value = xi[j]
63 | max_idx = 0
64 | if index_range:
65 | max_idx = index_range[-1]
66 | return ret, max_idx
67 |
68 | class svm_problem(Structure):
69 | _names = ["l", "y", "x"]
70 | _types = [c_int, POINTER(c_double), POINTER(POINTER(svm_node))]
71 | _fields_ = genFields(_names, _types)
72 |
73 | def __init__(self, y, x):
74 | if len(y) != len(x):
75 | raise ValueError("len(y) != len(x)")
76 | self.l = l = len(y)
77 |
78 | max_idx = 0
79 | x_space = self.x_space = []
80 | for i, xi in enumerate(x):
81 | tmp_xi, tmp_idx = gen_svm_nodearray(xi)
82 | x_space += [tmp_xi]
83 | max_idx = max(max_idx, tmp_idx)
84 | self.n = max_idx
85 |
86 | self.y = (c_double * l)()
87 | for i, yi in enumerate(y): self.y[i] = yi
88 |
89 | self.x = (POINTER(svm_node) * l)()
90 | for i, xi in enumerate(self.x_space): self.x[i] = xi
91 |
92 | class svm_parameter(Structure):
93 | _names = ["svm_type", "kernel_type", "degree", "gamma", "coef0",
94 | "cache_size", "eps", "C", "nr_weight", "weight_label", "weight",
95 | "nu", "p", "shrinking", "probability"]
96 | _types = [c_int, c_int, c_int, c_double, c_double,
97 | c_double, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double),
98 | c_double, c_double, c_int, c_int]
99 | _fields_ = genFields(_names, _types)
100 |
101 | def __init__(self, options = None):
102 | if options == None:
103 | options = ''
104 | self.parse_options(options)
105 |
106 | def show(self):
107 | attrs = svm_parameter._names + self.__dict__.keys()
108 | values = map(lambda attr: getattr(self, attr), attrs)
109 | for attr, val in zip(attrs, values):
110 | print(' %s: %s' % (attr, val))
111 |
112 | def set_to_default_values(self):
113 | self.svm_type = C_SVC;
114 | self.kernel_type = RBF
115 | self.degree = 3
116 | self.gamma = 0
117 | self.coef0 = 0
118 | self.nu = 0.5
119 | self.cache_size = 100
120 | self.C = 1
121 | self.eps = 0.001
122 | self.p = 0.1
123 | self.shrinking = 1
124 | self.probability = 0
125 | self.nr_weight = 0
126 | self.weight_label = (c_int*0)()
127 | self.weight = (c_double*0)()
128 | self.cross_validation = False
129 | self.nr_fold = 0
130 | self.print_func = None
131 |
132 | def parse_options(self, options):
133 | argv = options.split()
134 | self.set_to_default_values()
135 | self.print_func = cast(None, PRINT_STRING_FUN)
136 | weight_label = []
137 | weight = []
138 |
139 | i = 0
140 | while i < len(argv):
141 | if argv[i] == "-s":
142 | i = i + 1
143 | self.svm_type = int(argv[i])
144 | elif argv[i] == "-t":
145 | i = i + 1
146 | self.kernel_type = int(argv[i])
147 | elif argv[i] == "-d":
148 | i = i + 1
149 | self.degree = int(argv[i])
150 | elif argv[i] == "-g":
151 | i = i + 1
152 | self.gamma = float(argv[i])
153 | elif argv[i] == "-r":
154 | i = i + 1
155 | self.coef0 = float(argv[i])
156 | elif argv[i] == "-n":
157 | i = i + 1
158 | self.nu = float(argv[i])
159 | elif argv[i] == "-m":
160 | i = i + 1
161 | self.cache_size = float(argv[i])
162 | elif argv[i] == "-c":
163 | i = i + 1
164 | self.C = float(argv[i])
165 | elif argv[i] == "-e":
166 | i = i + 1
167 | self.eps = float(argv[i])
168 | elif argv[i] == "-p":
169 | i = i + 1
170 | self.p = float(argv[i])
171 | elif argv[i] == "-h":
172 | i = i + 1
173 | self.shrinking = int(argv[i])
174 | elif argv[i] == "-b":
175 | i = i + 1
176 | self.probability = int(argv[i])
177 | elif argv[i] == "-q":
178 | self.print_func = PRINT_STRING_FUN(print_null)
179 | elif argv[i] == "-v":
180 | i = i + 1
181 | self.cross_validation = 1
182 | self.nr_fold = int(argv[i])
183 | if self.nr_fold < 2:
184 | raise ValueError("n-fold cross validation: n must >= 2")
185 | elif argv[i].startswith("-w"):
186 | i = i + 1
187 | self.nr_weight += 1
188 | nr_weight = self.nr_weight
189 | weight_label += [int(argv[i-1][2:])]
190 | weight += [float(argv[i])]
191 | else:
192 | raise ValueError("Wrong options")
193 | i += 1
194 |
195 | libsvm.svm_set_print_string_function(self.print_func)
196 | self.weight_label = (c_int*self.nr_weight)()
197 | self.weight = (c_double*self.nr_weight)()
198 | for i in range(self.nr_weight):
199 | self.weight[i] = weight[i]
200 | self.weight_label[i] = weight_label[i]
201 |
202 | class svm_model(Structure):
203 | _names = ['param', 'nr_class', 'l', 'SV', 'sv_coef', 'rho',
204 | 'probA', 'probB', 'label', 'nSV', 'free_sv']
205 | _types = [svm_parameter, c_int, c_int, POINTER(POINTER(svm_node)),
206 | POINTER(POINTER(c_double)), POINTER(c_double),
207 | POINTER(c_double), POINTER(c_double), POINTER(c_int),
208 | POINTER(c_int), c_int]
209 | _fields_ = genFields(_names, _types)
210 |
211 | def __init__(self):
212 | self.__createfrom__ = 'python'
213 |
214 | def __del__(self):
215 | # free memory created by C to avoid memory leak
216 | if hasattr(self, '__createfrom__') and self.__createfrom__ == 'C':
217 | libsvm.svm_free_and_destroy_model(pointer(self))
218 |
219 | def get_svm_type(self):
220 | return libsvm.svm_get_svm_type(self)
221 |
222 | def get_nr_class(self):
223 | return libsvm.svm_get_nr_class(self)
224 |
225 | def get_svr_probability(self):
226 | return libsvm.svm_get_svr_probability(self)
227 |
228 | def get_labels(self):
229 | nr_class = self.get_nr_class()
230 | labels = (c_int * nr_class)()
231 | libsvm.svm_get_labels(self, labels)
232 | return labels[:nr_class]
233 |
234 | def is_probability_model(self):
235 | return (libsvm.svm_check_probability_model(self) == 1)
236 |
237 | def get_sv_coef(self):
238 | return [tuple(self.sv_coef[j][i] for j in xrange(self.nr_class - 1))
239 | for i in xrange(self.l)]
240 |
241 | def get_SV(self):
242 | result = []
243 | for sparse_sv in self.SV[:self.l]:
244 | row = dict()
245 |
246 | i = 0
247 | while True:
248 | row[sparse_sv[i].index] = sparse_sv[i].value
249 | if sparse_sv[i].index == -1:
250 | break
251 | i += 1
252 |
253 | result.append(row)
254 | return result
255 |
256 | def toPyModel(model_ptr):
257 | """
258 | toPyModel(model_ptr) -> svm_model
259 |
260 | Convert a ctypes POINTER(svm_model) to a Python svm_model
261 | """
262 | if bool(model_ptr) == False:
263 | raise ValueError("Null pointer")
264 | m = model_ptr.contents
265 | m.__createfrom__ = 'C'
266 | return m
267 |
268 | fillprototype(libsvm.svm_train, POINTER(svm_model), [POINTER(svm_problem), POINTER(svm_parameter)])
269 | fillprototype(libsvm.svm_cross_validation, None, [POINTER(svm_problem), POINTER(svm_parameter), c_int, POINTER(c_double)])
270 |
271 | fillprototype(libsvm.svm_save_model, c_int, [c_char_p, POINTER(svm_model)])
272 | fillprototype(libsvm.svm_load_model, POINTER(svm_model), [c_char_p])
273 |
274 | fillprototype(libsvm.svm_get_svm_type, c_int, [POINTER(svm_model)])
275 | fillprototype(libsvm.svm_get_nr_class, c_int, [POINTER(svm_model)])
276 | fillprototype(libsvm.svm_get_labels, None, [POINTER(svm_model), POINTER(c_int)])
277 | fillprototype(libsvm.svm_get_svr_probability, c_double, [POINTER(svm_model)])
278 |
279 | fillprototype(libsvm.svm_predict_values, c_double, [POINTER(svm_model), POINTER(svm_node), POINTER(c_double)])
280 | fillprototype(libsvm.svm_predict, c_double, [POINTER(svm_model), POINTER(svm_node)])
281 | fillprototype(libsvm.svm_predict_probability, c_double, [POINTER(svm_model), POINTER(svm_node), POINTER(c_double)])
282 |
283 | fillprototype(libsvm.svm_free_model_content, None, [POINTER(svm_model)])
284 | fillprototype(libsvm.svm_free_and_destroy_model, None, [POINTER(POINTER(svm_model))])
285 | fillprototype(libsvm.svm_destroy_param, None, [POINTER(svm_parameter)])
286 |
287 | fillprototype(libsvm.svm_check_parameter, c_char_p, [POINTER(svm_problem), POINTER(svm_parameter)])
288 | fillprototype(libsvm.svm_check_probability_model, c_int, [POINTER(svm_model)])
289 | fillprototype(libsvm.svm_set_print_string_function, None, [PRINT_STRING_FUN])
290 |
--------------------------------------------------------------------------------
/python/svmutil.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from svm import *
4 |
5 | def svm_read_problem(data_file_name):
6 | """
7 | svm_read_problem(data_file_name) -> [y, x]
8 |
9 | Read LIBSVM-format data from data_file_name and return labels y
10 | and data instances x.
11 | """
12 | prob_y = []
13 | prob_x = []
14 | for line in open(data_file_name):
15 | line = line.split(None, 1)
16 | # In case an instance with all zero features
17 | if len(line) == 1: line += ['']
18 | label, features = line
19 | xi = {}
20 | for e in features.split():
21 | ind, val = e.split(":")
22 | xi[int(ind)] = float(val)
23 | prob_y += [float(label)]
24 | prob_x += [xi]
25 | return (prob_y, prob_x)
26 |
27 | def svm_load_model(model_file_name):
28 | """
29 | svm_load_model(model_file_name) -> model
30 |
31 | Load a LIBSVM model from model_file_name and return.
32 | """
33 | model = libsvm.svm_load_model(model_file_name)
34 | if not model:
35 | print("can't open model file %s" % model_file_name)
36 | return None
37 | model = toPyModel(model)
38 | return model
39 |
40 | def svm_save_model(model_file_name, model):
41 | """
42 | svm_save_model(model_file_name, model) -> None
43 |
44 | Save a LIBSVM model to the file model_file_name.
45 | """
46 | libsvm.svm_save_model(model_file_name, model)
47 |
48 | def evaluations(ty, pv):
49 | """
50 | evaluations(ty, pv) -> (ACC, MSE, SCC)
51 |
52 | Calculate accuracy, mean squared error and squared correlation coefficient
53 | using the true values (ty) and predicted values (pv).
54 | """
55 | if len(ty) != len(pv):
56 | raise ValueError("len(ty) must equal to len(pv)")
57 | total_correct = total_error = 0
58 | sumv = sumy = sumvv = sumyy = sumvy = 0
59 | for v, y in zip(pv, ty):
60 | if y == v:
61 | total_correct += 1
62 | total_error += (v-y)*(v-y)
63 | sumv += v
64 | sumy += y
65 | sumvv += v*v
66 | sumyy += y*y
67 | sumvy += v*y
68 | l = len(ty)
69 | ACC = 100.0*total_correct/l
70 | MSE = total_error/l
71 | try:
72 | SCC = ((l*sumvy-sumv*sumy)*(l*sumvy-sumv*sumy))/((l*sumvv-sumv*sumv)*(l*sumyy-sumy*sumy))
73 | except:
74 | SCC = float('nan')
75 | return (ACC, MSE, SCC)
76 |
77 | def svm_train(arg1, arg2=None, arg3=None):
78 | """
79 | svm_train(y, x [, 'options']) -> model | ACC | MSE
80 | svm_train(prob, [, 'options']) -> model | ACC | MSE
81 | svm_train(prob, param) -> model | ACC| MSE
82 |
83 | Train an SVM model from data (y, x) or an svm_problem prob using
84 | 'options' or an svm_parameter param.
85 | If '-v' is specified in 'options' (i.e., cross validation)
86 | either accuracy (ACC) or mean-squared error (MSE) is returned.
87 | 'options':
88 | -s svm_type : set type of SVM (default 0)
89 | 0 -- C-SVC
90 | 1 -- nu-SVC
91 | 2 -- one-class SVM
92 | 3 -- epsilon-SVR
93 | 4 -- nu-SVR
94 | -t kernel_type : set type of kernel function (default 2)
95 | 0 -- linear: u'*v
96 | 1 -- polynomial: (gamma*u'*v + coef0)^degree
97 | 2 -- radial basis function: exp(-gamma*|u-v|^2)
98 | 3 -- sigmoid: tanh(gamma*u'*v + coef0)
99 | 4 -- precomputed kernel (kernel values in training_set_file)
100 | -d degree : set degree in kernel function (default 3)
101 | -g gamma : set gamma in kernel function (default 1/num_features)
102 | -r coef0 : set coef0 in kernel function (default 0)
103 | -c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
104 | -n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
105 | -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
106 | -m cachesize : set cache memory size in MB (default 100)
107 | -e epsilon : set tolerance of termination criterion (default 0.001)
108 | -h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)
109 | -b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
110 | -wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)
111 | -v n: n-fold cross validation mode
112 | -q : quiet mode (no outputs)
113 | """
114 | prob, param = None, None
115 | if isinstance(arg1, (list, tuple)):
116 | assert isinstance(arg2, (list, tuple))
117 | y, x, options = arg1, arg2, arg3
118 | prob = svm_problem(y, x)
119 | param = svm_parameter(options)
120 | elif isinstance(arg1, svm_problem):
121 | prob = arg1
122 | if isinstance(arg2, svm_parameter):
123 | param = arg2
124 | else:
125 | param = svm_parameter(arg2)
126 | if prob == None or param == None:
127 | raise TypeError("Wrong types for the arguments")
128 |
129 | if param.kernel_type == PRECOMPUTED:
130 | for xi in prob.x_space:
131 | idx, val = xi[0].index, xi[0].value
132 | if xi[0].index != 0:
133 | raise ValueError('Wrong input format: first column must be 0:sample_serial_number')
134 | if val <= 0 or val > prob.n:
135 | raise ValueError('Wrong input format: sample_serial_number out of range')
136 |
137 | if param.gamma == 0 and prob.n > 0:
138 | param.gamma = 1.0 / prob.n
139 | libsvm.svm_set_print_string_function(param.print_func)
140 | err_msg = libsvm.svm_check_parameter(prob, param)
141 | if err_msg:
142 | raise ValueError('Error: %s' % err_msg)
143 |
144 | if param.cross_validation:
145 | l, nr_fold = prob.l, param.nr_fold
146 | target = (c_double * l)()
147 | libsvm.svm_cross_validation(prob, param, nr_fold, target)
148 | ACC, MSE, SCC = evaluations(prob.y[:l], target[:l])
149 | if param.svm_type in [EPSILON_SVR, NU_SVR]:
150 | print("Cross Validation Mean squared error = %g" % MSE)
151 | print("Cross Validation Squared correlation coefficient = %g" % SCC)
152 | return MSE
153 | else:
154 | print("Cross Validation Accuracy = %g%%" % ACC)
155 | return ACC
156 | else:
157 | m = libsvm.svm_train(prob, param)
158 | m = toPyModel(m)
159 |
160 | # If prob is destroyed, data including SVs pointed by m can remain.
161 | m.x_space = prob.x_space
162 | return m
163 |
164 | def svm_predict(y, x, m, options=""):
165 | """
166 | svm_predict(y, x, m [, "options"]) -> (p_labels, p_acc, p_vals)
167 |
168 | Predict data (y, x) with the SVM model m.
169 | "options":
170 | -b probability_estimates: whether to predict probability estimates,
171 | 0 or 1 (default 0); for one-class SVM only 0 is supported.
172 |
173 | The return tuple contains
174 | p_labels: a list of predicted labels
175 | p_acc: a tuple including accuracy (for classification), mean-squared
176 | error, and squared correlation coefficient (for regression).
177 | p_vals: a list of decision values or probability estimates (if '-b 1'
178 | is specified). If k is the number of classes, for decision values,
179 | each element includes results of predicting k(k-1)/2 binary-class
180 | SVMs. For probabilities, each element contains k values indicating
181 | the probability that the testing instance is in each class.
182 | Note that the order of classes here is the same as 'model.label'
183 | field in the model structure.
184 | """
185 | predict_probability = 0
186 | argv = options.split()
187 | i = 0
188 | while i < len(argv):
189 | if argv[i] == '-b':
190 | i += 1
191 | predict_probability = int(argv[i])
192 | else:
193 | raise ValueError("Wrong options")
194 | i+=1
195 |
196 | svm_type = m.get_svm_type()
197 | is_prob_model = m.is_probability_model()
198 | nr_class = m.get_nr_class()
199 | pred_labels = []
200 | pred_values = []
201 |
202 | if predict_probability:
203 | if not is_prob_model:
204 | raise ValueError("Model does not support probabiliy estimates")
205 |
206 | if svm_type in [NU_SVR, EPSILON_SVR]:
207 | print("Prob. model for test data: target value = predicted value + z,\n"
208 | "z: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g" % m.get_svr_probability());
209 | nr_class = 0
210 |
211 | prob_estimates = (c_double * nr_class)()
212 | for xi in x:
213 | xi, idx = gen_svm_nodearray(xi)
214 | label = libsvm.svm_predict_probability(m, xi, prob_estimates)
215 | values = prob_estimates[:nr_class]
216 | pred_labels += [label]
217 | pred_values += [values]
218 | else:
219 | if is_prob_model:
220 | print("Model supports probability estimates, but disabled in predicton.")
221 | if svm_type in (ONE_CLASS, EPSILON_SVR, NU_SVC):
222 | nr_classifier = 1
223 | else:
224 | nr_classifier = nr_class*(nr_class-1)//2
225 | dec_values = (c_double * nr_classifier)()
226 | for xi in x:
227 | xi, idx = gen_svm_nodearray(xi)
228 | label = libsvm.svm_predict_values(m, xi, dec_values)
229 | values = dec_values[:nr_classifier]
230 | pred_labels += [label]
231 | pred_values += [values]
232 |
233 | ACC, MSE, SCC = evaluations(y, pred_labels)
234 | l = len(y)
235 | if svm_type in [EPSILON_SVR, NU_SVR]:
236 | print("Mean squared error = %g (regression)" % MSE)
237 | print("Squared correlation coefficient = %g (regression)" % SCC)
238 | else:
239 | print("Accuracy = %g%% (%d/%d) (classification)" % (ACC, int(l*ACC/100), l))
240 |
241 | return pred_labels, (ACC, MSE, SCC), pred_values
242 |
243 |
--------------------------------------------------------------------------------
/svm-analyze.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "svm.h"
8 |
9 | #define MIN(x, y) (x < y ? x : y)
10 |
11 | struct score_data
12 | {
13 | double label;
14 | double score;
15 | };
16 |
17 | struct svm_node *x;
18 | int max_nr_attr = 64;
19 |
20 | extern struct svm_model* model;
21 | int predict_probability=0;
22 | double min_threshold = 0, max_threshold = 0;
23 | bool min_set = false, max_set = false;
24 | int num_steps = 20;
25 |
26 | static char *line = NULL;
27 | static int max_line_len;
28 |
29 | extern static char* readline(FILE *input);
30 | void exit_input_error(int line_num);
31 |
32 | void analyze(FILE *input, FILE *output)
33 | {
34 | int correct = 0;
35 | int total = 0, inclass = 0;
36 | double error = 0;
37 | double sump = 0, sumt = 0, sumpp = 0, sumtt = 0, sumpt = 0;
38 |
39 | int svm_type=svm_get_svm_type(model);
40 | int nr_class=svm_get_nr_class(model);
41 | double *prob_estimates=NULL;
42 | int j;
43 | int max_scores = 64;
44 | struct score_data * scores = (struct score_data *) malloc(max_scores*sizeof(struct score_data));
45 |
46 | max_line_len = 1024;
47 | line = (char *)malloc(max_line_len*sizeof(char));
48 | while(readline(input) != NULL)
49 | {
50 | int i = 0;
51 | double target_label, predict_label;
52 | char *idx, *val, *label, *endptr;
53 | int inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has start from 0
54 |
55 | //Make sure we don't go over the bounds of our score array
56 | if (total >= max_scores)
57 | {
58 | max_scores *= 2;
59 | scores = (struct score_data *) realloc(scores, max_scores*sizeof(struct score_data));
60 | }
61 |
62 | label = strtok(line," \t\n");
63 | if(label == NULL) // empty line
64 | exit_input_error(total+1);
65 |
66 | target_label = strtod(label,&endptr);
67 | if(endptr == label || *endptr != '\0')
68 | exit_input_error(total+1);
69 |
70 | if (target_label > 0) ++inclass;
71 |
72 | while(1)
73 | {
74 | if(i>=max_nr_attr-1) // need one more for index = -1
75 | {
76 | max_nr_attr *= 2;
77 | x = (struct svm_node *) realloc(x,max_nr_attr*sizeof(struct svm_node));
78 | }
79 |
80 | idx = strtok(NULL,":");
81 | val = strtok(NULL," \t");
82 |
83 | if(val == NULL)
84 | break;
85 | errno = 0;
86 | x[i].index = (int) strtol(idx,&endptr,10);
87 | if(endptr == idx || errno != 0 || *endptr != '\0' || x[i].index <= inst_max_index)
88 | exit_input_error(total+1);
89 | else
90 | inst_max_index = x[i].index;
91 |
92 | errno = 0;
93 | x[i].value = strtod(val,&endptr);
94 | if(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
95 | exit_input_error(total+1);
96 |
97 | ++i;
98 | }
99 | x[i].index = -1;
100 |
101 | predict_label = svm_predict(model,x);
102 | //printf("%g %g\n", target_label, predict_label);
103 |
104 | scores[total].label = target_label;
105 | scores[total].score = predict_label;
106 |
107 | if((predict_label/fabs(predict_label)) == target_label)
108 | ++correct;
109 | error += (predict_label-target_label)*(predict_label-target_label);
110 | sump += predict_label;
111 | sumt += target_label;
112 | sumpp += predict_label*predict_label;
113 | sumtt += target_label*target_label;
114 | sumpt += predict_label*target_label;
115 | ++total;
116 | }
117 |
118 | //We have scores saved to file
119 | //It's easier to just read them back in
120 | double ma = 0, mi = 1; //Reasonable bounds on max/min to prevent outliers
121 | //from causing a poor p/r analysis.
122 | double step;
123 | double min_error = 0, min_error_m = 0, min_error_t = 0;
124 |
125 | for (int i = 0; i < total; i++)
126 | {
127 | ma = scores[i].score > ma ? scores[i].score : ma;
128 | mi = scores[i].score < mi ? scores[i].score : mi;
129 | }
130 |
131 | if (min_set)
132 | mi = mi > min_threshold ? mi : min_threshold;
133 | if (max_set)
134 | ma = ma < max_threshold ? ma : max_threshold;
135 |
136 | //fprintf(output, "%g, %g\n", ma, mi);
137 | step = (ma - mi)/num_steps;
138 | //Compute precision and recall
139 |
140 | for (int i = 0; i <= num_steps-1; i++)
141 | {
142 | double tl = mi + i*step;
143 | for (int j = i+1; j <= num_steps; j++)
144 | {
145 | double tu = mi + j*step;
146 | int retrieved = 0, relevant = 0;
147 | double precision = 0, recall = 0, fmeasure = 0, error = 0;
148 | double false_accept = 0, false_reject = 0;
149 |
150 | for (int i = 0; i < total; i++)
151 | {
152 | if (scores[i].score >= tl && scores[i].score <= tu)
153 | {
154 | retrieved++;
155 | if (scores[i].label > 0) // equals 1
156 | relevant++;
157 | else
158 | false_accept += MIN(fabs(scores[i].score - tl), fabs(tu - scores[i].score));
159 | //false_accept++;
160 | }
161 | else
162 | {
163 | if (scores[i].label > 0)
164 | false_reject += MIN(fabs(scores[i].score - tl), fabs(tu - scores[i].score));
165 | //false_reject++;
166 | }
167 | }
168 |
169 | error = fabs(false_accept - false_reject);
170 |
171 | if (retrieved > 0)
172 | precision = ((double) relevant)/retrieved;
173 | else
174 | precision = 0;
175 |
176 | recall = ((double) relevant)/inclass;
177 |
178 | fmeasure = 2*precision*recall/(precision + recall);
179 | if (precision > min_error)
180 | {
181 | min_error = precision;
182 | min_error_m = tl;
183 | min_error_t = tu;
184 | }
185 |
186 | //fprintf(output, "%g\t%g\t%g\t%g\n", precision, recall, tl, tu);
187 | }
188 | }
189 |
190 | free(scores);
191 |
192 | printf("min: %g, max: %g, error: %g\n", min_error_m, min_error_t, min_error);
193 | }
194 |
195 | /*
196 | int main(int argc, char **argv)
197 | {
198 | FILE *input, *output;
199 | int i;
200 |
201 | // parse options
202 | for(i=1;i=argc-2)
228 | exit_with_help();
229 |
230 | input = fopen(argv[i],"r");
231 | if(input == NULL)
232 | {
233 | fprintf(stderr,"can't open input file %s\n",argv[i]);
234 | exit(1);
235 | }
236 |
237 | output = fopen(argv[i+2],"w+");
238 | if(output == NULL)
239 | {
240 | fprintf(stderr,"can't open output file %s\n",argv[i+2]);
241 | exit(1);
242 | }
243 |
244 | if((model=svm_load_model(argv[i+1]))==0)
245 | {
246 | fprintf(stderr,"can't open model file %s\n",argv[i+1]);
247 | exit(1);
248 | }
249 |
250 | x = (struct svm_node *) malloc(max_nr_attr*sizeof(struct svm_node));
251 | if(predict_probability)
252 | {
253 | if(svm_check_probability_model(model)==0)
254 | {
255 | fprintf(stderr,"Model does not support probabiliy estimates\n");
256 | exit(1);
257 | }
258 | }
259 | else
260 | {
261 | if(svm_check_probability_model(model)!=0)
262 | printf("Model supports probability estimates, but disabled in prediction.\n");
263 | }
264 | predict(input,output);
265 | svm_free_and_destroy_model(&model);
266 | free(x);
267 | free(line);
268 | fclose(input);
269 | fclose(output);
270 | return 0;
271 | }
272 | */
273 |
--------------------------------------------------------------------------------
/svm-scale.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | void exit_with_help()
8 | {
9 | printf(
10 | "Usage: svm-scale [options] data_filename\n"
11 | "options:\n"
12 | "-l lower : x scaling lower limit (default -1)\n"
13 | "-u upper : x scaling upper limit (default +1)\n"
14 | "-y y_lower y_upper : y scaling limits (default: no y scaling)\n"
15 | "-s save_filename : save scaling parameters to save_filename\n"
16 | "-r restore_filename : restore scaling parameters from restore_filename\n"
17 | );
18 | exit(1);
19 | }
20 |
21 | char *line = NULL;
22 | int max_line_len = 1024;
23 | double lower=-1.0,upper=1.0,y_lower,y_upper;
24 | int y_scaling = 0;
25 | double *feature_max;
26 | double *feature_min;
27 | double y_max = -DBL_MAX;
28 | double y_min = DBL_MAX;
29 | int max_index;
30 | long int num_nonzeros = 0;
31 | long int new_num_nonzeros = 0;
32 |
33 | #define max(x,y) (((x)>(y))?(x):(y))
34 | #define min(x,y) (((x)<(y))?(x):(y))
35 |
36 | void output_target(double value);
37 | void output(int index, double value);
38 | char* readline(FILE *input);
39 |
40 | int main(int argc,char **argv)
41 | {
42 | int i,index;
43 | FILE *fp, *fp_restore = NULL;
44 | char *save_filename = NULL;
45 | char *restore_filename = NULL;
46 |
47 | for(i=1;i lower) || (y_scaling && !(y_upper > y_lower)))
70 | {
71 | fprintf(stderr,"inconsistent lower/upper specification\n");
72 | exit(1);
73 | }
74 |
75 | if(restore_filename && save_filename)
76 | {
77 | fprintf(stderr,"cannot use -r and -s simultaneously\n");
78 | exit(1);
79 | }
80 |
81 | if(argc != i+1)
82 | exit_with_help();
83 |
84 | fp=fopen(argv[i],"r");
85 |
86 | if(fp==NULL)
87 | {
88 | fprintf(stderr,"can't open file %s\n", argv[i]);
89 | exit(1);
90 | }
91 |
92 | line = (char *) malloc(max_line_len*sizeof(char));
93 |
94 | #define SKIP_TARGET\
95 | while(isspace(*p)) ++p;\
96 | while(!isspace(*p)) ++p;
97 |
98 | #define SKIP_ELEMENT\
99 | while(*p!=':') ++p;\
100 | ++p;\
101 | while(isspace(*p)) ++p;\
102 | while(*p && !isspace(*p)) ++p;
103 |
104 | /* assumption: min index of attributes is 1 */
105 | /* pass 1: find out max index of attributes */
106 | max_index = 0;
107 |
108 | if(restore_filename)
109 | {
110 | int idx, c;
111 |
112 | fp_restore = fopen(restore_filename,"r");
113 | if(fp_restore==NULL)
114 | {
115 | fprintf(stderr,"can't open file %s\n", restore_filename);
116 | exit(1);
117 | }
118 |
119 | c = fgetc(fp_restore);
120 | if(c == 'y')
121 | {
122 | readline(fp_restore);
123 | readline(fp_restore);
124 | readline(fp_restore);
125 | }
126 | readline(fp_restore);
127 | readline(fp_restore);
128 |
129 | while(fscanf(fp_restore,"%d %*f %*f\n",&idx) == 1)
130 | max_index = max(idx,max_index);
131 | rewind(fp_restore);
132 | }
133 |
134 | while(readline(fp)!=NULL)
135 | {
136 | char *p=line;
137 |
138 | SKIP_TARGET
139 |
140 | while(sscanf(p,"%d:%*f",&index)==1)
141 | {
142 | max_index = max(max_index, index);
143 | SKIP_ELEMENT
144 | num_nonzeros++;
145 | }
146 | }
147 | rewind(fp);
148 |
149 | feature_max = (double *)malloc((max_index+1)* sizeof(double));
150 | feature_min = (double *)malloc((max_index+1)* sizeof(double));
151 |
152 | if(feature_max == NULL || feature_min == NULL)
153 | {
154 | fprintf(stderr,"can't allocate enough memory\n");
155 | exit(1);
156 | }
157 |
158 | for(i=0;i<=max_index;i++)
159 | {
160 | feature_max[i]=-DBL_MAX;
161 | feature_min[i]=DBL_MAX;
162 | }
163 |
164 | /* pass 2: find out min/max value */
165 | while(readline(fp)!=NULL)
166 | {
167 | char *p=line;
168 | int next_index=1;
169 | double target;
170 | double value;
171 |
172 | sscanf(p,"%lf",&target);
173 | y_max = max(y_max,target);
174 | y_min = min(y_min,target);
175 |
176 | SKIP_TARGET
177 |
178 | while(sscanf(p,"%d:%lf",&index,&value)==2)
179 | {
180 | for(i=next_index;i num_nonzeros)
288 | fprintf(stderr,
289 | "Warning: original #nonzeros %ld\n"
290 | " new #nonzeros %ld\n"
291 | "Use -l 0 if many original feature values are zeros\n",
292 | num_nonzeros, new_num_nonzeros);
293 |
294 | free(line);
295 | free(feature_max);
296 | free(feature_min);
297 | fclose(fp);
298 | return 0;
299 | }
300 |
301 | char* readline(FILE *input)
302 | {
303 | int len;
304 |
305 | if(fgets(line,max_line_len,input) == NULL)
306 | return NULL;
307 |
308 | while(strrchr(line,'\n') == NULL)
309 | {
310 | max_line_len *= 2;
311 | line = (char *) realloc(line, max_line_len);
312 | len = (int) strlen(line);
313 | if(fgets(line+len,max_line_len-len,input) == NULL)
314 | break;
315 | }
316 | return line;
317 | }
318 |
319 | void output_target(double value)
320 | {
321 | if(y_scaling)
322 | {
323 | if(value == y_min)
324 | value = y_lower;
325 | else if(value == y_max)
326 | value = y_upper;
327 | else value = y_lower + (y_upper-y_lower) *
328 | (value - y_min)/(y_max-y_min);
329 | }
330 | printf("%g ",value);
331 | }
332 |
333 | void output(int index, double value)
334 | {
335 | /* skip single-valued attribute */
336 | if(feature_max[index] == feature_min[index])
337 | return;
338 |
339 | if(value == feature_min[index])
340 | value = lower;
341 | else if(value == feature_max[index])
342 | value = upper;
343 | else
344 | value = lower + (upper-lower) *
345 | (value-feature_min[index])/
346 | (feature_max[index]-feature_min[index]);
347 |
348 | if(value != 0)
349 | {
350 | printf("%d:%g ",index, value);
351 | new_num_nonzeros++;
352 | }
353 | }
354 |
--------------------------------------------------------------------------------
/svm-toy/gtk/Makefile:
--------------------------------------------------------------------------------
1 | CC? = gcc
2 | CXX? = g++
3 | CFLAGS = -Wall -O3 -g `pkg-config --cflags gtk+-2.0`
4 | LIBS = `pkg-config --libs gtk+-2.0`
5 |
6 | svm-toy: main.o interface.o callbacks.o ../../svm.o
7 | $(CXX) $(CFLAGS) main.o interface.o callbacks.o ../../svm.o -o svm-toy $(LIBS)
8 |
9 | main.o: main.c
10 | $(CC) $(CFLAGS) -c main.c
11 |
12 | interface.o: interface.c interface.h
13 | $(CC) $(CFLAGS) -c interface.c
14 |
15 | callbacks.o: callbacks.cpp callbacks.h
16 | $(CXX) $(CFLAGS) -c callbacks.cpp
17 |
18 | ../../svm.o:
19 | cd ../..; make svm.o
20 |
21 | clean:
22 | rm -f *~ callbacks.o svm-toy main.o interface.o callbacks.o ../../svm.o
23 |
--------------------------------------------------------------------------------
/svm-toy/gtk/callbacks.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "callbacks.h"
7 | #include "interface.h"
8 | #include "../../svm.h"
9 | using namespace std;
10 |
11 | #define DEFAULT_PARAM "-t 2 -c 100"
12 | #define XLEN 500
13 | #define YLEN 500
14 |
15 | GdkColor colors[] =
16 | {
17 | {0,0,0,0},
18 | {0,0,120<<8,120<<8},
19 | {0,120<<8,120<<8,0},
20 | {0,120<<8,0,120<<8},
21 | {0,0,200<<8,200<<8},
22 | {0,200<<8,200<<8,0},
23 | {0,200<<8,0,200<<8},
24 | };
25 |
26 | GdkGC *gc;
27 | GdkPixmap *pixmap;
28 | extern "C" GtkWidget *draw_main;
29 | GtkWidget *draw_main;
30 | extern "C" GtkWidget *entry_option;
31 | GtkWidget *entry_option;
32 |
33 | typedef struct {
34 | double x, y;
35 | signed char value;
36 | } point;
37 |
38 | list point_list;
39 | int current_value = 1;
40 |
41 | extern "C" void svm_toy_initialize()
42 | {
43 | gboolean success[7];
44 |
45 | gdk_colormap_alloc_colors(
46 | gdk_colormap_get_system(),
47 | colors,
48 | 7,
49 | FALSE,
50 | TRUE,
51 | success);
52 |
53 | gc = gdk_gc_new(draw_main->window);
54 | pixmap = gdk_pixmap_new(draw_main->window,XLEN,YLEN,-1);
55 | gdk_gc_set_foreground(gc,&colors[0]);
56 | gdk_draw_rectangle(pixmap,gc,TRUE,0,0,XLEN,YLEN);
57 | gtk_entry_set_text(GTK_ENTRY(entry_option),DEFAULT_PARAM);
58 | }
59 |
60 | void redraw_area(GtkWidget* widget, int x, int y, int w, int h)
61 | {
62 | gdk_draw_pixmap(widget->window,
63 | gc,
64 | pixmap,
65 | x,y,x,y,w,h);
66 | }
67 |
68 | void draw_point(const point& p)
69 | {
70 | gdk_gc_set_foreground(gc,&colors[p.value+3]);
71 | gdk_draw_rectangle(pixmap, gc, TRUE,int(p.x*XLEN),int(p.y*YLEN),4,4);
72 | gdk_draw_rectangle(draw_main->window, gc, TRUE,int(p.x*XLEN),int(p.y*YLEN),4,4);
73 | }
74 |
75 | void draw_all_points()
76 | {
77 | for(list::iterator p = point_list.begin(); p != point_list.end();p++)
78 | draw_point(*p);
79 | }
80 |
81 | void clear_all()
82 | {
83 | point_list.clear();
84 | gdk_gc_set_foreground(gc,&colors[0]);
85 | gdk_draw_rectangle(pixmap,gc,TRUE,0,0,XLEN,YLEN);
86 | redraw_area(draw_main,0,0,XLEN,YLEN);
87 | }
88 |
89 | void
90 | on_button_change_clicked (GtkButton *button,
91 | gpointer user_data)
92 | {
93 | ++current_value;
94 | if(current_value > 3) current_value = 1;
95 | }
96 |
97 | void
98 | on_button_run_clicked (GtkButton *button,
99 | gpointer user_data)
100 | {
101 | // guard
102 | if(point_list.empty()) return;
103 |
104 | svm_parameter param;
105 | int i,j;
106 |
107 | // default values
108 | param.svm_type = C_SVC;
109 | param.kernel_type = RBF;
110 | param.degree = 3;
111 | param.gamma = 0;
112 | param.coef0 = 0;
113 | param.nu = 0.5;
114 | param.cache_size = 100;
115 | param.C = 1;
116 | param.eps = 1e-3;
117 | param.p = 0.1;
118 | param.shrinking = 1;
119 | param.probability = 0;
120 | param.nr_weight = 0;
121 | param.weight_label = NULL;
122 | param.weight = NULL;
123 |
124 | // parse options
125 | const char *p = gtk_entry_get_text(GTK_ENTRY(entry_option));
126 |
127 | while (1) {
128 | while (*p && *p != '-')
129 | p++;
130 |
131 | if (*p == '\0')
132 | break;
133 |
134 | p++;
135 | switch (*p++) {
136 | case 's':
137 | param.svm_type = atoi(p);
138 | break;
139 | case 't':
140 | param.kernel_type = atoi(p);
141 | break;
142 | case 'd':
143 | param.degree = atoi(p);
144 | break;
145 | case 'g':
146 | param.gamma = atof(p);
147 | break;
148 | case 'r':
149 | param.coef0 = atof(p);
150 | break;
151 | case 'n':
152 | param.nu = atof(p);
153 | break;
154 | case 'm':
155 | param.cache_size = atof(p);
156 | break;
157 | case 'c':
158 | param.C = atof(p);
159 | break;
160 | case 'e':
161 | param.eps = atof(p);
162 | break;
163 | case 'p':
164 | param.p = atof(p);
165 | break;
166 | case 'h':
167 | param.shrinking = atoi(p);
168 | break;
169 | case 'b':
170 | param.probability = atoi(p);
171 | break;
172 | case 'w':
173 | ++param.nr_weight;
174 | param.weight_label = (int *)realloc(param.weight_label,sizeof(int)*param.nr_weight);
175 | param.weight = (double *)realloc(param.weight,sizeof(double)*param.nr_weight);
176 | param.weight_label[param.nr_weight-1] = atoi(p);
177 | while(*p && !isspace(*p)) ++p;
178 | param.weight[param.nr_weight-1] = atof(p);
179 | break;
180 | }
181 | }
182 |
183 | // build problem
184 | svm_problem prob;
185 |
186 | prob.l = point_list.size();
187 | prob.y = new double[prob.l];
188 |
189 | if(param.kernel_type == PRECOMPUTED)
190 | {
191 | }
192 | else if(param.svm_type == EPSILON_SVR ||
193 | param.svm_type == NU_SVR)
194 | {
195 | if(param.gamma == 0) param.gamma = 1;
196 | svm_node *x_space = new svm_node[2 * prob.l];
197 | prob.x = new svm_node *[prob.l];
198 |
199 | i = 0;
200 | for (list ::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
201 | {
202 | x_space[2 * i].index = 1;
203 | x_space[2 * i].value = q->x;
204 | x_space[2 * i + 1].index = -1;
205 | prob.x[i] = &x_space[2 * i];
206 | prob.y[i] = q->y;
207 | }
208 |
209 | // build model & classify
210 | svm_model *model = svm_train(&prob, ¶m);
211 | svm_node x[2];
212 | x[0].index = 1;
213 | x[1].index = -1;
214 | int *j = new int[XLEN];
215 |
216 | for (i = 0; i < XLEN; i++)
217 | {
218 | x[0].value = (double) i / XLEN;
219 | j[i] = (int)(YLEN*svm_predict(model, x));
220 | }
221 |
222 | gdk_gc_set_foreground(gc,&colors[0]);
223 | gdk_draw_line(pixmap,gc,0,0,0,YLEN-1);
224 | gdk_draw_line(draw_main->window,gc,0,0,0,YLEN-1);
225 |
226 | int p = (int)(param.p * YLEN);
227 | for(i = 1; i < XLEN; i++)
228 | {
229 | gdk_gc_set_foreground(gc,&colors[0]);
230 | gdk_draw_line(pixmap,gc,i,0,i,YLEN-1);
231 | gdk_draw_line(draw_main->window,gc,i,0,i,YLEN-1);
232 |
233 | gdk_gc_set_foreground(gc,&colors[5]);
234 | gdk_draw_line(pixmap,gc,i-1,j[i-1],i,j[i]);
235 | gdk_draw_line(draw_main->window,gc,i-1,j[i-1],i,j[i]);
236 |
237 | if(param.svm_type == EPSILON_SVR)
238 | {
239 | gdk_gc_set_foreground(gc,&colors[2]);
240 | gdk_draw_line(pixmap,gc,i-1,j[i-1]+p,i,j[i]+p);
241 | gdk_draw_line(draw_main->window,gc,i-1,j[i-1]+p,i,j[i]+p);
242 |
243 | gdk_gc_set_foreground(gc,&colors[2]);
244 | gdk_draw_line(pixmap,gc,i-1,j[i-1]-p,i,j[i]-p);
245 | gdk_draw_line(draw_main->window,gc,i-1,j[i-1]-p,i,j[i]-p);
246 | }
247 | }
248 |
249 | svm_free_and_destroy_model(&model);
250 | delete[] j;
251 | delete[] x_space;
252 | delete[] prob.x;
253 | delete[] prob.y;
254 | }
255 | else
256 | {
257 | if(param.gamma == 0) param.gamma = 0.5;
258 | svm_node *x_space = new svm_node[3 * prob.l];
259 | prob.x = new svm_node *[prob.l];
260 |
261 | i = 0;
262 | for (list ::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
263 | {
264 | x_space[3 * i].index = 1;
265 | x_space[3 * i].value = q->x;
266 | x_space[3 * i + 1].index = 2;
267 | x_space[3 * i + 1].value = q->y;
268 | x_space[3 * i + 2].index = -1;
269 | prob.x[i] = &x_space[3 * i];
270 | prob.y[i] = q->value;
271 | }
272 |
273 | // build model & classify
274 | svm_model *model = svm_train(&prob, ¶m);
275 | svm_node x[3];
276 | x[0].index = 1;
277 | x[1].index = 2;
278 | x[2].index = -1;
279 |
280 | for (i = 0; i < XLEN; i++)
281 | for (j = 0; j < YLEN; j++) {
282 | x[0].value = (double) i / XLEN;
283 | x[1].value = (double) j / YLEN;
284 | double d = svm_predict(model, x);
285 | if (param.svm_type == ONE_CLASS && d<0) d=2;
286 | gdk_gc_set_foreground(gc,&colors[(int)d]);
287 | gdk_draw_point(pixmap,gc,i,j);
288 | gdk_draw_point(draw_main->window,gc,i,j);
289 | }
290 |
291 | svm_free_and_destroy_model(&model);
292 | delete[] x_space;
293 | delete[] prob.x;
294 | delete[] prob.y;
295 | }
296 | free(param.weight_label);
297 | free(param.weight);
298 | draw_all_points();
299 | }
300 |
301 | void
302 | on_button_clear_clicked (GtkButton *button,
303 | gpointer user_data)
304 | {
305 | clear_all();
306 | }
307 |
308 | void
309 | on_window1_destroy (GtkObject *object,
310 | gpointer user_data)
311 | {
312 | gtk_exit(0);
313 | }
314 |
315 | gboolean
316 | on_draw_main_button_press_event (GtkWidget *widget,
317 | GdkEventButton *event,
318 | gpointer user_data)
319 | {
320 | point p = {(double)event->x/XLEN, (double)event->y/YLEN, current_value};
321 | point_list.push_back(p);
322 | draw_point(p);
323 | return FALSE;
324 | }
325 |
326 | gboolean
327 | on_draw_main_expose_event (GtkWidget *widget,
328 | GdkEventExpose *event,
329 | gpointer user_data)
330 | {
331 | redraw_area(widget,
332 | event->area.x, event->area.y,
333 | event->area.width, event->area.height);
334 | return FALSE;
335 | }
336 |
337 | GtkWidget *fileselection;
338 | static enum { SAVE, LOAD } fileselection_flag;
339 |
340 | void show_fileselection()
341 | {
342 | fileselection = create_fileselection();
343 | gtk_signal_connect_object(
344 | GTK_OBJECT(GTK_FILE_SELECTION(fileselection)->ok_button),
345 | "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
346 | (GtkObject *) fileselection);
347 |
348 | gtk_signal_connect_object (GTK_OBJECT
349 | (GTK_FILE_SELECTION(fileselection)->cancel_button),
350 | "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
351 | (GtkObject *) fileselection);
352 |
353 | gtk_widget_show(fileselection);
354 | }
355 |
356 | void
357 | on_button_save_clicked (GtkButton *button,
358 | gpointer user_data)
359 | {
360 | fileselection_flag = SAVE;
361 | show_fileselection();
362 | }
363 |
364 |
365 | void
366 | on_button_load_clicked (GtkButton *button,
367 | gpointer user_data)
368 | {
369 | fileselection_flag = LOAD;
370 | show_fileselection();
371 | }
372 |
373 | void
374 | on_filesel_ok_clicked (GtkButton *button,
375 | gpointer user_data)
376 | {
377 | gtk_widget_hide(fileselection);
378 | const char *filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
379 |
380 | if(fileselection_flag == SAVE)
381 | {
382 | FILE *fp = fopen(filename,"w");
383 | if(fp)
384 | {
385 | for(list::iterator p = point_list.begin(); p != point_list.end();p++)
386 | fprintf(fp,"%d 1:%f 2:%f\n", p->value, p->x, p->y);
387 | fclose(fp);
388 | }
389 |
390 | }
391 | else if(fileselection_flag == LOAD)
392 | {
393 | FILE *fp = fopen(filename,"r");
394 | if(fp)
395 | {
396 | clear_all();
397 | char buf[4096];
398 | while(fgets(buf,sizeof(buf),fp))
399 | {
400 | int v;
401 | double x,y;
402 | if(sscanf(buf,"%d%*d:%lf%*d:%lf",&v,&x,&y)!=3)
403 | break;
404 | point p = {x,y,v};
405 | point_list.push_back(p);
406 | }
407 | fclose(fp);
408 | draw_all_points();
409 | }
410 | }
411 | }
412 |
413 | void
414 | on_fileselection_destroy (GtkObject *object,
415 | gpointer user_data)
416 | {
417 | }
418 |
419 | void
420 | on_filesel_cancel_clicked (GtkButton *button,
421 | gpointer user_data)
422 | {
423 | }
424 |
--------------------------------------------------------------------------------
/svm-toy/gtk/callbacks.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 |
7 | void
8 | on_window1_destroy (GtkObject *object,
9 | gpointer user_data);
10 |
11 | gboolean
12 | on_draw_main_button_press_event (GtkWidget *widget,
13 | GdkEventButton *event,
14 | gpointer user_data);
15 |
16 | gboolean
17 | on_draw_main_expose_event (GtkWidget *widget,
18 | GdkEventExpose *event,
19 | gpointer user_data);
20 |
21 | void
22 | on_button_change_clicked (GtkButton *button,
23 | gpointer user_data);
24 |
25 | void
26 | on_button_run_clicked (GtkButton *button,
27 | gpointer user_data);
28 |
29 | void
30 | on_button_clear_clicked (GtkButton *button,
31 | gpointer user_data);
32 |
33 | void
34 | on_button_save_clicked (GtkButton *button,
35 | gpointer user_data);
36 |
37 | void
38 | on_button_load_clicked (GtkButton *button,
39 | gpointer user_data);
40 |
41 | void
42 | on_fileselection_destroy (GtkObject *object,
43 | gpointer user_data);
44 |
45 | void
46 | on_filesel_ok_clicked (GtkButton *button,
47 | gpointer user_data);
48 |
49 | void
50 | on_filesel_cancel_clicked (GtkButton *button,
51 | gpointer user_data);
52 | #ifdef __cplusplus
53 | }
54 | #endif
55 |
--------------------------------------------------------------------------------
/svm-toy/gtk/interface.c:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT EDIT THIS FILE - it is generated by Glade.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 |
13 | #include "callbacks.h"
14 | #include "interface.h"
15 |
16 | GtkWidget*
17 | create_window (void)
18 | {
19 | GtkWidget *window;
20 | GtkWidget *vbox1;
21 | extern GtkWidget *draw_main;
22 | GtkWidget *hbox1;
23 | GtkWidget *button_change;
24 | GtkWidget *button_run;
25 | GtkWidget *button_clear;
26 | GtkWidget *button_save;
27 | GtkWidget *button_load;
28 | extern GtkWidget *entry_option;
29 |
30 | window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
31 | gtk_object_set_data (GTK_OBJECT (window), "window", window);
32 | gtk_window_set_title (GTK_WINDOW (window), "SVM Toy");
33 |
34 | vbox1 = gtk_vbox_new (FALSE, 0);
35 | gtk_widget_ref (vbox1);
36 | gtk_object_set_data_full (GTK_OBJECT (window), "vbox1", vbox1,
37 | (GtkDestroyNotify) gtk_widget_unref);
38 | gtk_widget_show (vbox1);
39 | gtk_container_add (GTK_CONTAINER (window), vbox1);
40 |
41 | draw_main = gtk_drawing_area_new ();
42 | gtk_widget_ref (draw_main);
43 | gtk_object_set_data_full (GTK_OBJECT (window), "draw_main", draw_main,
44 | (GtkDestroyNotify) gtk_widget_unref);
45 | gtk_widget_show (draw_main);
46 | gtk_box_pack_start (GTK_BOX (vbox1), draw_main, TRUE, TRUE, 0);
47 | gtk_widget_set_usize (draw_main, 500, 500);
48 | gtk_widget_set_events (draw_main, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
49 |
50 | hbox1 = gtk_hbox_new (FALSE, 0);
51 | gtk_widget_ref (hbox1);
52 | gtk_object_set_data_full (GTK_OBJECT (window), "hbox1", hbox1,
53 | (GtkDestroyNotify) gtk_widget_unref);
54 | gtk_widget_show (hbox1);
55 | gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
56 |
57 | button_change = gtk_button_new_with_label ("Change");
58 | gtk_widget_ref (button_change);
59 | gtk_object_set_data_full (GTK_OBJECT (window), "button_change", button_change,
60 | (GtkDestroyNotify) gtk_widget_unref);
61 | gtk_widget_show (button_change);
62 | gtk_box_pack_start (GTK_BOX (hbox1), button_change, FALSE, FALSE, 0);
63 |
64 | button_run = gtk_button_new_with_label ("Run");
65 | gtk_widget_ref (button_run);
66 | gtk_object_set_data_full (GTK_OBJECT (window), "button_run", button_run,
67 | (GtkDestroyNotify) gtk_widget_unref);
68 | gtk_widget_show (button_run);
69 | gtk_box_pack_start (GTK_BOX (hbox1), button_run, FALSE, FALSE, 0);
70 |
71 | button_clear = gtk_button_new_with_label ("Clear");
72 | gtk_widget_ref (button_clear);
73 | gtk_object_set_data_full (GTK_OBJECT (window), "button_clear", button_clear,
74 | (GtkDestroyNotify) gtk_widget_unref);
75 | gtk_widget_show (button_clear);
76 | gtk_box_pack_start (GTK_BOX (hbox1), button_clear, FALSE, FALSE, 0);
77 |
78 | button_save = gtk_button_new_with_label ("Save");
79 | gtk_widget_ref (button_save);
80 | gtk_object_set_data_full (GTK_OBJECT (window), "button_save", button_save,
81 | (GtkDestroyNotify) gtk_widget_unref);
82 | gtk_widget_show (button_save);
83 | gtk_box_pack_start (GTK_BOX (hbox1), button_save, FALSE, FALSE, 0);
84 |
85 | button_load = gtk_button_new_with_label ("Load");
86 | gtk_widget_ref (button_load);
87 | gtk_object_set_data_full (GTK_OBJECT (window), "button_load", button_load,
88 | (GtkDestroyNotify) gtk_widget_unref);
89 | gtk_widget_show (button_load);
90 | gtk_box_pack_start (GTK_BOX (hbox1), button_load, FALSE, FALSE, 0);
91 |
92 | entry_option = gtk_entry_new ();
93 | gtk_widget_ref (entry_option);
94 | gtk_object_set_data_full (GTK_OBJECT (window), "entry_option", entry_option,
95 | (GtkDestroyNotify) gtk_widget_unref);
96 | gtk_widget_show (entry_option);
97 | gtk_box_pack_start (GTK_BOX (hbox1), entry_option, TRUE, TRUE, 0);
98 |
99 | gtk_signal_connect (GTK_OBJECT (window), "destroy",
100 | GTK_SIGNAL_FUNC (on_window1_destroy),
101 | NULL);
102 | gtk_signal_connect (GTK_OBJECT (draw_main), "button_press_event",
103 | GTK_SIGNAL_FUNC (on_draw_main_button_press_event),
104 | NULL);
105 | gtk_signal_connect (GTK_OBJECT (draw_main), "expose_event",
106 | GTK_SIGNAL_FUNC (on_draw_main_expose_event),
107 | NULL);
108 | gtk_signal_connect (GTK_OBJECT (button_change), "clicked",
109 | GTK_SIGNAL_FUNC (on_button_change_clicked),
110 | NULL);
111 | gtk_signal_connect (GTK_OBJECT (button_run), "clicked",
112 | GTK_SIGNAL_FUNC (on_button_run_clicked),
113 | NULL);
114 | gtk_signal_connect (GTK_OBJECT (button_clear), "clicked",
115 | GTK_SIGNAL_FUNC (on_button_clear_clicked),
116 | NULL);
117 | gtk_signal_connect (GTK_OBJECT (button_save), "clicked",
118 | GTK_SIGNAL_FUNC (on_button_save_clicked),
119 | NULL);
120 | gtk_signal_connect (GTK_OBJECT (button_load), "clicked",
121 | GTK_SIGNAL_FUNC (on_button_load_clicked),
122 | NULL);
123 | gtk_signal_connect (GTK_OBJECT (entry_option), "activate",
124 | GTK_SIGNAL_FUNC (on_button_run_clicked),
125 | NULL);
126 |
127 | return window;
128 | }
129 |
130 | GtkWidget*
131 | create_fileselection (void)
132 | {
133 | GtkWidget *fileselection;
134 | GtkWidget *filesel_ok;
135 | GtkWidget *filesel_cancel;
136 |
137 | fileselection = gtk_file_selection_new ("Select File");
138 | gtk_object_set_data (GTK_OBJECT (fileselection), "fileselection", fileselection);
139 | gtk_container_set_border_width (GTK_CONTAINER (fileselection), 10);
140 | gtk_window_set_modal (GTK_WINDOW (fileselection), TRUE);
141 |
142 | filesel_ok = GTK_FILE_SELECTION (fileselection)->ok_button;
143 | gtk_object_set_data (GTK_OBJECT (fileselection), "filesel_ok", filesel_ok);
144 | gtk_widget_show (filesel_ok);
145 | GTK_WIDGET_SET_FLAGS (filesel_ok, GTK_CAN_DEFAULT);
146 |
147 | filesel_cancel = GTK_FILE_SELECTION (fileselection)->cancel_button;
148 | gtk_object_set_data (GTK_OBJECT (fileselection), "filesel_cancel", filesel_cancel);
149 | gtk_widget_show (filesel_cancel);
150 | GTK_WIDGET_SET_FLAGS (filesel_cancel, GTK_CAN_DEFAULT);
151 |
152 | gtk_signal_connect (GTK_OBJECT (fileselection), "destroy",
153 | GTK_SIGNAL_FUNC (on_fileselection_destroy),
154 | NULL);
155 | gtk_signal_connect (GTK_OBJECT (filesel_ok), "clicked",
156 | GTK_SIGNAL_FUNC (on_filesel_ok_clicked),
157 | NULL);
158 | gtk_signal_connect (GTK_OBJECT (filesel_cancel), "clicked",
159 | GTK_SIGNAL_FUNC (on_filesel_cancel_clicked),
160 | NULL);
161 |
162 | return fileselection;
163 | }
164 |
165 |
--------------------------------------------------------------------------------
/svm-toy/gtk/interface.h:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT EDIT THIS FILE - it is generated by Glade.
3 | */
4 |
5 | #ifdef __cplusplus
6 | extern "C" {
7 | #endif
8 |
9 | GtkWidget* create_window (void);
10 | GtkWidget* create_fileselection (void);
11 |
12 | #ifdef __cplusplus
13 | }
14 | #endif
15 |
--------------------------------------------------------------------------------
/svm-toy/gtk/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Initial main.c file generated by Glade. Edit as required.
3 | * Glade will not overwrite this file.
4 | */
5 |
6 | #include
7 | #include "interface.h"
8 | void svm_toy_initialize();
9 |
10 | int main (int argc, char *argv[])
11 | {
12 | GtkWidget *window;
13 |
14 | gtk_set_locale ();
15 | gtk_init (&argc, &argv);
16 |
17 | window = create_window ();
18 | gtk_widget_show (window);
19 |
20 | svm_toy_initialize();
21 | gtk_main ();
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/svm-toy/gtk/svm-toy.glade:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | svm-toy
6 | svm-toy
7 |
8 | src
9 | pixmaps
10 | C
11 | False
12 | False
13 | False
14 | True
15 | True
16 | True
17 | False
18 | interface.c
19 | interface.h
20 | callbacks.c
21 | callbacks.h
22 | support.c
23 | support.h
24 |
25 |
26 |
27 |
28 | GtkWindow
29 | window
30 |
31 | destroy
32 | on_window1_destroy
33 | Sun, 16 Apr 2000 09:47:10 GMT
34 |
35 | SVM Toy
36 | GTK_WINDOW_TOPLEVEL
37 | GTK_WIN_POS_NONE
38 | False
39 | False
40 | True
41 | False
42 |
43 |
44 | GtkVBox
45 | vbox1
46 | False
47 | 0
48 |
49 |
50 | GtkDrawingArea
51 | draw_main
52 | 500
53 | 500
54 | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
55 |
56 | button_press_event
57 | on_draw_main_button_press_event
58 | Sun, 16 Apr 2000 13:02:05 GMT
59 |
60 |
61 | expose_event
62 | on_draw_main_expose_event
63 | Sun, 16 Apr 2000 14:27:05 GMT
64 |
65 |
66 | 0
67 | True
68 | True
69 |
70 |
71 |
72 |
73 | GtkHBox
74 | hbox1
75 | False
76 | 0
77 |
78 | 0
79 | False
80 | False
81 |
82 |
83 |
84 | GtkButton
85 | button_change
86 | True
87 |
88 | clicked
89 | on_button_change_clicked
90 | Sun, 16 Apr 2000 09:40:18 GMT
91 |
92 |
93 |
94 | 0
95 | False
96 | False
97 |
98 |
99 |
100 |
101 | GtkButton
102 | button_run
103 | True
104 |
105 | clicked
106 | on_button_run_clicked
107 | Sun, 16 Apr 2000 09:40:37 GMT
108 |
109 |
110 |
111 | 0
112 | False
113 | False
114 |
115 |
116 |
117 |
118 | GtkButton
119 | button_clear
120 | True
121 |
122 | clicked
123 | on_button_clear_clicked
124 | Sun, 16 Apr 2000 09:40:44 GMT
125 |
126 |
127 |
128 | 0
129 | False
130 | False
131 |
132 |
133 |
134 |
135 | GtkButton
136 | button_save
137 | True
138 |
139 | clicked
140 | on_button_save_clicked
141 | Fri, 16 Jun 2000 18:23:46 GMT
142 |
143 |
144 |
145 | 0
146 | False
147 | False
148 |
149 |
150 |
151 |
152 | GtkButton
153 | button_load
154 | True
155 |
156 | clicked
157 | on_button_load_clicked
158 | Fri, 16 Jun 2000 18:23:56 GMT
159 |
160 |
161 |
162 | 0
163 | False
164 | False
165 |
166 |
167 |
168 |
169 | GtkEntry
170 | entry_option
171 | True
172 |
173 | activate
174 | on_button_run_clicked
175 | Sun, 16 Apr 2000 09:42:46 GMT
176 |
177 | True
178 | True
179 | 0
180 |
181 |
182 | 0
183 | True
184 | True
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | GtkFileSelection
193 | fileselection
194 | 10
195 |
196 | destroy
197 | on_fileselection_destroy
198 | Fri, 16 Jun 2000 18:11:28 GMT
199 |
200 | Select File
201 | GTK_WINDOW_TOPLEVEL
202 | GTK_WIN_POS_NONE
203 | True
204 | False
205 | True
206 | False
207 | True
208 |
209 |
210 | GtkButton
211 | FileSel:ok_button
212 | filesel_ok
213 | True
214 | True
215 |
216 | clicked
217 | on_filesel_ok_clicked
218 | Fri, 16 Jun 2000 18:09:56 GMT
219 |
220 |
221 |
222 |
223 |
224 | GtkButton
225 | FileSel:cancel_button
226 | filesel_cancel
227 | True
228 | True
229 |
230 | clicked
231 | on_filesel_cancel_clicked
232 | Fri, 16 Jun 2000 18:09:46 GMT
233 |
234 |
235 |
236 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/svm-toy/qt/Makefile:
--------------------------------------------------------------------------------
1 | CXX? = g++
2 | CFLAGS = -Wall -O3 -I$(INCLUDE) -I$(INCLUDE)/QtGui -lQtGui
3 | INCLUDE = /usr/include/qt4
4 | MOC = /usr/bin/moc-qt4
5 |
6 | svm-toy: svm-toy.cpp svm-toy.moc ../../svm.o
7 | $(CXX) $(CFLAGS) svm-toy.cpp ../../svm.o -o svm-toy
8 |
9 | svm-toy.moc: svm-toy.cpp
10 | $(MOC) svm-toy.cpp -o svm-toy.moc
11 |
12 | ../../svm.o:
13 | cd ../..; make svm.o
14 |
15 | clean:
16 | rm -f *~ svm-toy svm-toy.moc ../../svm.o
17 |
18 |
--------------------------------------------------------------------------------
/svm-toy/qt/svm-toy.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "../../svm.h"
7 | using namespace std;
8 |
9 | #define DEFAULT_PARAM "-t 2 -c 100"
10 | #define XLEN 500
11 | #define YLEN 500
12 |
13 | QRgb colors[] =
14 | {
15 | qRgb(0,0,0),
16 | qRgb(0,120,120),
17 | qRgb(120,120,0),
18 | qRgb(120,0,120),
19 | qRgb(0,200,200),
20 | qRgb(200,200,0),
21 | qRgb(200,0,200)
22 | };
23 |
24 | class SvmToyWindow : public QWidget
25 | {
26 |
27 | Q_OBJECT
28 |
29 | public:
30 | SvmToyWindow();
31 | ~SvmToyWindow();
32 | protected:
33 | virtual void mousePressEvent( QMouseEvent* );
34 | virtual void paintEvent( QPaintEvent* );
35 |
36 | private:
37 | QPixmap buffer;
38 | QPixmap icon1;
39 | QPixmap icon2;
40 | QPixmap icon3;
41 | QPushButton button_change_icon;
42 | QPushButton button_run;
43 | QPushButton button_clear;
44 | QPushButton button_save;
45 | QPushButton button_load;
46 | QLineEdit input_line;
47 | QPainter buffer_painter;
48 | struct point {
49 | double x, y;
50 | signed char value;
51 | };
52 | list point_list;
53 | int current_value;
54 | const QPixmap& choose_icon(int v)
55 | {
56 | if(v==1) return icon1;
57 | else if(v==2) return icon2;
58 | else return icon3;
59 | }
60 | void clear_all()
61 | {
62 | point_list.clear();
63 | buffer.fill(Qt::black);
64 | repaint();
65 | }
66 | void draw_point(const point& p)
67 | {
68 | const QPixmap& icon = choose_icon(p.value);
69 | buffer_painter.drawPixmap((int)(p.x*XLEN),(int)(p.y*YLEN),icon);
70 | repaint();
71 | }
72 | void draw_all_points()
73 | {
74 | for(list::iterator p = point_list.begin(); p != point_list.end();p++)
75 | draw_point(*p);
76 | }
77 | private slots:
78 | void button_change_icon_clicked()
79 | {
80 | ++current_value;
81 | if(current_value > 3) current_value = 1;
82 | button_change_icon.setIcon(choose_icon(current_value));
83 | }
84 | void button_run_clicked()
85 | {
86 | // guard
87 | if(point_list.empty()) return;
88 |
89 | svm_parameter param;
90 | int i,j;
91 |
92 | // default values
93 | param.svm_type = C_SVC;
94 | param.kernel_type = RBF;
95 | param.degree = 3;
96 | param.gamma = 0;
97 | param.coef0 = 0;
98 | param.nu = 0.5;
99 | param.cache_size = 100;
100 | param.C = 1;
101 | param.eps = 1e-3;
102 | param.p = 0.1;
103 | param.shrinking = 1;
104 | param.probability = 0;
105 | param.nr_weight = 0;
106 | param.weight_label = NULL;
107 | param.weight = NULL;
108 |
109 | // parse options
110 | const char *p = input_line.text().toAscii().constData();
111 |
112 | while (1) {
113 | while (*p && *p != '-')
114 | p++;
115 |
116 | if (*p == '\0')
117 | break;
118 |
119 | p++;
120 | switch (*p++) {
121 | case 's':
122 | param.svm_type = atoi(p);
123 | break;
124 | case 't':
125 | param.kernel_type = atoi(p);
126 | break;
127 | case 'd':
128 | param.degree = atoi(p);
129 | break;
130 | case 'g':
131 | param.gamma = atof(p);
132 | break;
133 | case 'r':
134 | param.coef0 = atof(p);
135 | break;
136 | case 'n':
137 | param.nu = atof(p);
138 | break;
139 | case 'm':
140 | param.cache_size = atof(p);
141 | break;
142 | case 'c':
143 | param.C = atof(p);
144 | break;
145 | case 'e':
146 | param.eps = atof(p);
147 | break;
148 | case 'p':
149 | param.p = atof(p);
150 | break;
151 | case 'h':
152 | param.shrinking = atoi(p);
153 | break;
154 | case 'b':
155 | param.probability = atoi(p);
156 | break;
157 | case 'w':
158 | ++param.nr_weight;
159 | param.weight_label = (int *)realloc(param.weight_label,sizeof(int)*param.nr_weight);
160 | param.weight = (double *)realloc(param.weight,sizeof(double)*param.nr_weight);
161 | param.weight_label[param.nr_weight-1] = atoi(p);
162 | while(*p && !isspace(*p)) ++p;
163 | param.weight[param.nr_weight-1] = atof(p);
164 | break;
165 | }
166 | }
167 |
168 | // build problem
169 | svm_problem prob;
170 |
171 | prob.l = point_list.size();
172 | prob.y = new double[prob.l];
173 |
174 | if(param.kernel_type == PRECOMPUTED)
175 | {
176 | }
177 | else if(param.svm_type == EPSILON_SVR ||
178 | param.svm_type == NU_SVR)
179 | {
180 | if(param.gamma == 0) param.gamma = 1;
181 | svm_node *x_space = new svm_node[2 * prob.l];
182 | prob.x = new svm_node *[prob.l];
183 |
184 | i = 0;
185 | for (list ::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
186 | {
187 | x_space[2 * i].index = 1;
188 | x_space[2 * i].value = q->x;
189 | x_space[2 * i + 1].index = -1;
190 | prob.x[i] = &x_space[2 * i];
191 | prob.y[i] = q->y;
192 | }
193 |
194 | // build model & classify
195 | svm_model *model = svm_train(&prob, ¶m);
196 | svm_node x[2];
197 | x[0].index = 1;
198 | x[1].index = -1;
199 | int *j = new int[XLEN];
200 |
201 | for (i = 0; i < XLEN; i++)
202 | {
203 | x[0].value = (double) i / XLEN;
204 | j[i] = (int)(YLEN*svm_predict(model, x));
205 | }
206 |
207 | buffer_painter.setPen(colors[0]);
208 | buffer_painter.drawLine(0,0,0,YLEN-1);
209 |
210 | int p = (int)(param.p * YLEN);
211 | for(i = 1; i < XLEN; i++)
212 | {
213 | buffer_painter.setPen(colors[0]);
214 | buffer_painter.drawLine(i,0,i,YLEN-1);
215 |
216 | buffer_painter.setPen(colors[5]);
217 | buffer_painter.drawLine(i-1,j[i-1],i,j[i]);
218 |
219 | if(param.svm_type == EPSILON_SVR)
220 | {
221 | buffer_painter.setPen(colors[2]);
222 | buffer_painter.drawLine(i-1,j[i-1]+p,i,j[i]+p);
223 |
224 | buffer_painter.setPen(colors[2]);
225 | buffer_painter.drawLine(i-1,j[i-1]-p,i,j[i]-p);
226 | }
227 | }
228 |
229 | svm_free_and_destroy_model(&model);
230 | delete[] j;
231 | delete[] x_space;
232 | delete[] prob.x;
233 | delete[] prob.y;
234 | }
235 | else
236 | {
237 | if(param.gamma == 0) param.gamma = 0.5;
238 | svm_node *x_space = new svm_node[3 * prob.l];
239 | prob.x = new svm_node *[prob.l];
240 |
241 | i = 0;
242 | for (list ::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
243 | {
244 | x_space[3 * i].index = 1;
245 | x_space[3 * i].value = q->x;
246 | x_space[3 * i + 1].index = 2;
247 | x_space[3 * i + 1].value = q->y;
248 | x_space[3 * i + 2].index = -1;
249 | prob.x[i] = &x_space[3 * i];
250 | prob.y[i] = q->value;
251 | }
252 |
253 | // build model & classify
254 | svm_model *model = svm_train(&prob, ¶m);
255 | svm_node x[3];
256 | x[0].index = 1;
257 | x[1].index = 2;
258 | x[2].index = -1;
259 |
260 | for (i = 0; i < XLEN; i++)
261 | for (j = 0; j < YLEN ; j++) {
262 | x[0].value = (double) i / XLEN;
263 | x[1].value = (double) j / YLEN;
264 | double d = svm_predict(model, x);
265 | if (param.svm_type == ONE_CLASS && d<0) d=2;
266 | buffer_painter.setPen(colors[(int)d]);
267 | buffer_painter.drawPoint(i,j);
268 | }
269 |
270 | svm_free_and_destroy_model(&model);
271 | delete[] x_space;
272 | delete[] prob.x;
273 | delete[] prob.y;
274 | }
275 | free(param.weight_label);
276 | free(param.weight);
277 | draw_all_points();
278 | }
279 | void button_clear_clicked()
280 | {
281 | clear_all();
282 | }
283 | void button_save_clicked()
284 | {
285 | QString filename = QFileDialog::getSaveFileName();
286 | if(!filename.isNull())
287 | {
288 | FILE *fp = fopen(filename.toAscii().constData(),"w");
289 | if(fp)
290 | {
291 | for(list::iterator p = point_list.begin(); p != point_list.end();p++)
292 | fprintf(fp,"%d 1:%f 2:%f\n", p->value, p->x, p->y);
293 | fclose(fp);
294 | }
295 | }
296 | }
297 | void button_load_clicked()
298 | {
299 | QString filename = QFileDialog::getOpenFileName();
300 | if(!filename.isNull())
301 | {
302 | FILE *fp = fopen(filename.toAscii().constData(),"r");
303 | if(fp)
304 | {
305 | clear_all();
306 | char buf[4096];
307 | while(fgets(buf,sizeof(buf),fp))
308 | {
309 | int v;
310 | double x,y;
311 | if(sscanf(buf,"%d%*d:%lf%*d:%lf",&v,&x,&y)!=3)
312 | break;
313 | point p = {x,y,v};
314 | point_list.push_back(p);
315 | }
316 | fclose(fp);
317 | draw_all_points();
318 | }
319 | }
320 |
321 | }
322 | };
323 |
324 | #include "svm-toy.moc"
325 |
326 | SvmToyWindow::SvmToyWindow()
327 | :button_change_icon(this)
328 | ,button_run("Run",this)
329 | ,button_clear("Clear",this)
330 | ,button_save("Save",this)
331 | ,button_load("Load",this)
332 | ,input_line(this)
333 | ,current_value(1)
334 | {
335 | buffer = QPixmap(XLEN,YLEN);
336 | buffer.fill(Qt::black);
337 |
338 | buffer_painter.begin(&buffer);
339 |
340 | QObject::connect(&button_change_icon, SIGNAL(clicked()), this,
341 | SLOT(button_change_icon_clicked()));
342 | QObject::connect(&button_run, SIGNAL(clicked()), this,
343 | SLOT(button_run_clicked()));
344 | QObject::connect(&button_clear, SIGNAL(clicked()), this,
345 | SLOT(button_clear_clicked()));
346 | QObject::connect(&button_save, SIGNAL(clicked()), this,
347 | SLOT(button_save_clicked()));
348 | QObject::connect(&button_load, SIGNAL(clicked()), this,
349 | SLOT(button_load_clicked()));
350 | QObject::connect(&input_line, SIGNAL(returnPressed()), this,
351 | SLOT(button_run_clicked()));
352 |
353 | // don't blank the window before repainting
354 | setAttribute(Qt::WA_NoBackground);
355 |
356 | icon1 = QPixmap(4,4);
357 | icon2 = QPixmap(4,4);
358 | icon3 = QPixmap(4,4);
359 |
360 |
361 | QPainter painter;
362 | painter.begin(&icon1);
363 | painter.fillRect(0,0,4,4,QBrush(colors[4]));
364 | painter.end();
365 |
366 | painter.begin(&icon2);
367 | painter.fillRect(0,0,4,4,QBrush(colors[5]));
368 | painter.end();
369 |
370 | painter.begin(&icon3);
371 | painter.fillRect(0,0,4,4,QBrush(colors[6]));
372 | painter.end();
373 |
374 | button_change_icon.setGeometry( 0, YLEN, 50, 25 );
375 | button_run.setGeometry( 50, YLEN, 50, 25 );
376 | button_clear.setGeometry( 100, YLEN, 50, 25 );
377 | button_save.setGeometry( 150, YLEN, 50, 25);
378 | button_load.setGeometry( 200, YLEN, 50, 25);
379 | input_line.setGeometry( 250, YLEN, 250, 25);
380 |
381 | input_line.setText(DEFAULT_PARAM);
382 | button_change_icon.setIcon(icon1);
383 | }
384 |
385 | SvmToyWindow::~SvmToyWindow()
386 | {
387 | buffer_painter.end();
388 | }
389 |
390 | void SvmToyWindow::mousePressEvent( QMouseEvent* event )
391 | {
392 | point p = {(double)event->x()/XLEN, (double)event->y()/YLEN, current_value};
393 | point_list.push_back(p);
394 | draw_point(p);
395 | }
396 |
397 | void SvmToyWindow::paintEvent( QPaintEvent* )
398 | {
399 | // copy the image from the buffer pixmap to the window
400 | QPainter p(this);
401 | p.drawPixmap(0, 0, buffer);
402 | }
403 |
404 | int main( int argc, char* argv[] )
405 | {
406 | QApplication myapp( argc, argv );
407 |
408 | SvmToyWindow* mywidget = new SvmToyWindow();
409 | mywidget->setGeometry( 100, 100, XLEN, YLEN+25 );
410 |
411 | mywidget->show();
412 | return myapp.exec();
413 | }
414 |
--------------------------------------------------------------------------------
/svm-toy/windows/svm-toy.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "../../svm.h"
7 | using namespace std;
8 |
9 | #define DEFAULT_PARAM "-t 2 -c 100"
10 | #define XLEN 500
11 | #define YLEN 500
12 | #define DrawLine(dc,x1,y1,x2,y2,c) \
13 | do { \
14 | HPEN hpen = CreatePen(PS_SOLID,0,c); \
15 | HPEN horig = SelectPen(dc,hpen); \
16 | MoveToEx(dc,x1,y1,NULL); \
17 | LineTo(dc,x2,y2); \
18 | SelectPen(dc,horig); \
19 | DeletePen(hpen); \
20 | } while(0)
21 |
22 | using namespace std;
23 |
24 | COLORREF colors[] =
25 | {
26 | RGB(0,0,0),
27 | RGB(0,120,120),
28 | RGB(120,120,0),
29 | RGB(120,0,120),
30 | RGB(0,200,200),
31 | RGB(200,200,0),
32 | RGB(200,0,200)
33 | };
34 |
35 | HWND main_window;
36 | HBITMAP buffer;
37 | HDC window_dc;
38 | HDC buffer_dc;
39 | HBRUSH brush1, brush2, brush3;
40 | HWND edit;
41 |
42 | enum {
43 | ID_BUTTON_CHANGE, ID_BUTTON_RUN, ID_BUTTON_CLEAR,
44 | ID_BUTTON_LOAD, ID_BUTTON_SAVE, ID_EDIT
45 | };
46 |
47 | struct point {
48 | double x, y;
49 | signed char value;
50 | };
51 |
52 | list point_list;
53 | int current_value = 1;
54 |
55 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
56 |
57 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
58 | PSTR szCmdLine, int iCmdShow)
59 | {
60 | static char szAppName[] = "SvmToy";
61 | MSG msg;
62 | WNDCLASSEX wndclass;
63 |
64 | wndclass.cbSize = sizeof(wndclass);
65 | wndclass.style = CS_HREDRAW | CS_VREDRAW;
66 | wndclass.lpfnWndProc = WndProc;
67 | wndclass.cbClsExtra = 0;
68 | wndclass.cbWndExtra = 0;
69 | wndclass.hInstance = hInstance;
70 | wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
71 | wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
72 | wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
73 | wndclass.lpszMenuName = NULL;
74 | wndclass.lpszClassName = szAppName;
75 | wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
76 |
77 | RegisterClassEx(&wndclass);
78 |
79 | main_window = CreateWindow(szAppName, // window class name
80 | "SVM Toy", // window caption
81 | WS_OVERLAPPEDWINDOW,// window style
82 | CW_USEDEFAULT, // initial x position
83 | CW_USEDEFAULT, // initial y position
84 | XLEN, // initial x size
85 | YLEN+52, // initial y size
86 | NULL, // parent window handle
87 | NULL, // window menu handle
88 | hInstance, // program instance handle
89 | NULL); // creation parameters
90 |
91 | ShowWindow(main_window, iCmdShow);
92 | UpdateWindow(main_window);
93 |
94 | CreateWindow("button", "Change", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
95 | 0, YLEN, 50, 25, main_window, (HMENU) ID_BUTTON_CHANGE, hInstance, NULL);
96 | CreateWindow("button", "Run", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
97 | 50, YLEN, 50, 25, main_window, (HMENU) ID_BUTTON_RUN, hInstance, NULL);
98 | CreateWindow("button", "Clear", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
99 | 100, YLEN, 50, 25, main_window, (HMENU) ID_BUTTON_CLEAR, hInstance, NULL);
100 | CreateWindow("button", "Save", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
101 | 150, YLEN, 50, 25, main_window, (HMENU) ID_BUTTON_SAVE, hInstance, NULL);
102 | CreateWindow("button", "Load", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
103 | 200, YLEN, 50, 25, main_window, (HMENU) ID_BUTTON_LOAD, hInstance, NULL);
104 |
105 | edit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE,
106 | 250, YLEN, 250, 25, main_window, (HMENU) ID_EDIT, hInstance, NULL);
107 |
108 | Edit_SetText(edit,DEFAULT_PARAM);
109 |
110 | brush1 = CreateSolidBrush(colors[4]);
111 | brush2 = CreateSolidBrush(colors[5]);
112 | brush3 = CreateSolidBrush(colors[6]);
113 |
114 | window_dc = GetDC(main_window);
115 | buffer = CreateCompatibleBitmap(window_dc, XLEN, YLEN);
116 | buffer_dc = CreateCompatibleDC(window_dc);
117 | SelectObject(buffer_dc, buffer);
118 | PatBlt(buffer_dc, 0, 0, XLEN, YLEN, BLACKNESS);
119 |
120 | while (GetMessage(&msg, NULL, 0, 0)) {
121 | TranslateMessage(&msg);
122 | DispatchMessage(&msg);
123 | }
124 | return msg.wParam;
125 | }
126 |
127 | int getfilename( HWND hWnd , char *filename, int len, int save)
128 | {
129 | OPENFILENAME OpenFileName;
130 | memset(&OpenFileName,0,sizeof(OpenFileName));
131 | filename[0]='\0';
132 |
133 | OpenFileName.lStructSize = sizeof(OPENFILENAME);
134 | OpenFileName.hwndOwner = hWnd;
135 | OpenFileName.lpstrFile = filename;
136 | OpenFileName.nMaxFile = len;
137 | OpenFileName.Flags = 0;
138 |
139 | return save?GetSaveFileName(&OpenFileName):GetOpenFileName(&OpenFileName);
140 | }
141 |
142 | void clear_all()
143 | {
144 | point_list.clear();
145 | PatBlt(buffer_dc, 0, 0, XLEN, YLEN, BLACKNESS);
146 | InvalidateRect(main_window, 0, 0);
147 | }
148 |
149 | HBRUSH choose_brush(int v)
150 | {
151 | if(v==1) return brush1;
152 | else if(v==2) return brush2;
153 | else return brush3;
154 | }
155 |
156 | void draw_point(const point & p)
157 | {
158 | RECT rect;
159 | rect.left = int(p.x*XLEN);
160 | rect.top = int(p.y*YLEN);
161 | rect.right = int(p.x*XLEN) + 3;
162 | rect.bottom = int(p.y*YLEN) + 3;
163 | FillRect(window_dc, &rect, choose_brush(p.value));
164 | FillRect(buffer_dc, &rect, choose_brush(p.value));
165 | }
166 |
167 | void draw_all_points()
168 | {
169 | for(list::iterator p = point_list.begin(); p != point_list.end(); p++)
170 | draw_point(*p);
171 | }
172 |
173 | void button_run_clicked()
174 | {
175 | // guard
176 | if(point_list.empty()) return;
177 |
178 | svm_parameter param;
179 | int i,j;
180 |
181 | // default values
182 | param.svm_type = C_SVC;
183 | param.kernel_type = RBF;
184 | param.degree = 3;
185 | param.gamma = 0;
186 | param.coef0 = 0;
187 | param.nu = 0.5;
188 | param.cache_size = 100;
189 | param.C = 1;
190 | param.eps = 1e-3;
191 | param.p = 0.1;
192 | param.shrinking = 1;
193 | param.probability = 0;
194 | param.nr_weight = 0;
195 | param.weight_label = NULL;
196 | param.weight = NULL;
197 |
198 | // parse options
199 | char str[1024];
200 | Edit_GetLine(edit, 0, str, sizeof(str));
201 | const char *p = str;
202 |
203 | while (1) {
204 | while (*p && *p != '-')
205 | p++;
206 |
207 | if (*p == '\0')
208 | break;
209 |
210 | p++;
211 | switch (*p++) {
212 | case 's':
213 | param.svm_type = atoi(p);
214 | break;
215 | case 't':
216 | param.kernel_type = atoi(p);
217 | break;
218 | case 'd':
219 | param.degree = atoi(p);
220 | break;
221 | case 'g':
222 | param.gamma = atof(p);
223 | break;
224 | case 'r':
225 | param.coef0 = atof(p);
226 | break;
227 | case 'n':
228 | param.nu = atof(p);
229 | break;
230 | case 'm':
231 | param.cache_size = atof(p);
232 | break;
233 | case 'c':
234 | param.C = atof(p);
235 | break;
236 | case 'e':
237 | param.eps = atof(p);
238 | break;
239 | case 'p':
240 | param.p = atof(p);
241 | break;
242 | case 'h':
243 | param.shrinking = atoi(p);
244 | break;
245 | case 'b':
246 | param.probability = atoi(p);
247 | break;
248 | case 'w':
249 | ++param.nr_weight;
250 | param.weight_label = (int *)realloc(param.weight_label,sizeof(int)*param.nr_weight);
251 | param.weight = (double *)realloc(param.weight,sizeof(double)*param.nr_weight);
252 | param.weight_label[param.nr_weight-1] = atoi(p);
253 | while(*p && !isspace(*p)) ++p;
254 | param.weight[param.nr_weight-1] = atof(p);
255 | break;
256 | }
257 | }
258 |
259 | // build problem
260 | svm_problem prob;
261 |
262 | prob.l = point_list.size();
263 | prob.y = new double[prob.l];
264 |
265 | if(param.kernel_type == PRECOMPUTED)
266 | {
267 | }
268 | else if(param.svm_type == EPSILON_SVR ||
269 | param.svm_type == NU_SVR)
270 | {
271 | if(param.gamma == 0) param.gamma = 1;
272 | svm_node *x_space = new svm_node[2 * prob.l];
273 | prob.x = new svm_node *[prob.l];
274 |
275 | i = 0;
276 | for (list::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
277 | {
278 | x_space[2 * i].index = 1;
279 | x_space[2 * i].value = q->x;
280 | x_space[2 * i + 1].index = -1;
281 | prob.x[i] = &x_space[2 * i];
282 | prob.y[i] = q->y;
283 | }
284 |
285 | // build model & classify
286 | svm_model *model = svm_train(&prob, ¶m);
287 | svm_node x[2];
288 | x[0].index = 1;
289 | x[1].index = -1;
290 | int *j = new int[XLEN];
291 |
292 | for (i = 0; i < XLEN; i++)
293 | {
294 | x[0].value = (double) i / XLEN;
295 | j[i] = (int)(YLEN*svm_predict(model, x));
296 | }
297 |
298 | DrawLine(buffer_dc,0,0,0,YLEN,colors[0]);
299 | DrawLine(window_dc,0,0,0,YLEN,colors[0]);
300 |
301 | int p = (int)(param.p * YLEN);
302 | for(int i=1; i < XLEN; i++)
303 | {
304 | DrawLine(buffer_dc,i,0,i,YLEN,colors[0]);
305 | DrawLine(window_dc,i,0,i,YLEN,colors[0]);
306 |
307 | DrawLine(buffer_dc,i-1,j[i-1],i,j[i],colors[5]);
308 | DrawLine(window_dc,i-1,j[i-1],i,j[i],colors[5]);
309 |
310 | if(param.svm_type == EPSILON_SVR)
311 | {
312 | DrawLine(buffer_dc,i-1,j[i-1]+p,i,j[i]+p,colors[2]);
313 | DrawLine(window_dc,i-1,j[i-1]+p,i,j[i]+p,colors[2]);
314 |
315 | DrawLine(buffer_dc,i-1,j[i-1]-p,i,j[i]-p,colors[2]);
316 | DrawLine(window_dc,i-1,j[i-1]-p,i,j[i]-p,colors[2]);
317 | }
318 | }
319 |
320 | svm_free_and_destroy_model(&model);
321 | delete[] j;
322 | delete[] x_space;
323 | delete[] prob.x;
324 | delete[] prob.y;
325 | }
326 | else
327 | {
328 | if(param.gamma == 0) param.gamma = 0.5;
329 | svm_node *x_space = new svm_node[3 * prob.l];
330 | prob.x = new svm_node *[prob.l];
331 |
332 | i = 0;
333 | for (list::iterator q = point_list.begin(); q != point_list.end(); q++, i++)
334 | {
335 | x_space[3 * i].index = 1;
336 | x_space[3 * i].value = q->x;
337 | x_space[3 * i + 1].index = 2;
338 | x_space[3 * i + 1].value = q->y;
339 | x_space[3 * i + 2].index = -1;
340 | prob.x[i] = &x_space[3 * i];
341 | prob.y[i] = q->value;
342 | }
343 |
344 | // build model & classify
345 | svm_model *model = svm_train(&prob, ¶m);
346 | svm_node x[3];
347 | x[0].index = 1;
348 | x[1].index = 2;
349 | x[2].index = -1;
350 |
351 | for (i = 0; i < XLEN; i++)
352 | for (j = 0; j < YLEN; j++) {
353 | x[0].value = (double) i / XLEN;
354 | x[1].value = (double) j / YLEN;
355 | double d = svm_predict(model, x);
356 | if (param.svm_type == ONE_CLASS && d<0) d=2;
357 | SetPixel(window_dc, i, j, colors[(int)d]);
358 | SetPixel(buffer_dc, i, j, colors[(int)d]);
359 | }
360 |
361 | svm_free_and_destroy_model(&model);
362 | delete[] x_space;
363 | delete[] prob.x;
364 | delete[] prob.y;
365 | }
366 | free(param.weight_label);
367 | free(param.weight);
368 | draw_all_points();
369 | }
370 |
371 | LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
372 | {
373 | HDC hdc;
374 | PAINTSTRUCT ps;
375 |
376 | switch (iMsg) {
377 | case WM_LBUTTONDOWN:
378 | {
379 | int x = LOWORD(lParam);
380 | int y = HIWORD(lParam);
381 | point p = {(double)x/XLEN, (double)y/YLEN, current_value};
382 | point_list.push_back(p);
383 | draw_point(p);
384 | }
385 | return 0;
386 | case WM_PAINT:
387 | {
388 | hdc = BeginPaint(hwnd, &ps);
389 | BitBlt(hdc, 0, 0, XLEN, YLEN, buffer_dc, 0, 0, SRCCOPY);
390 | EndPaint(hwnd, &ps);
391 | }
392 | return 0;
393 | case WM_COMMAND:
394 | {
395 | int id = LOWORD(wParam);
396 | switch (id) {
397 | case ID_BUTTON_CHANGE:
398 | ++current_value;
399 | if(current_value > 3) current_value = 1;
400 | break;
401 | case ID_BUTTON_RUN:
402 | button_run_clicked();
403 | break;
404 | case ID_BUTTON_CLEAR:
405 | clear_all();
406 | break;
407 | case ID_BUTTON_SAVE:
408 | {
409 | char filename[1024];
410 | if(getfilename(hwnd,filename,1024,1))
411 | {
412 | FILE *fp = fopen(filename,"w");
413 | if(fp)
414 | {
415 | for (list::iterator p = point_list.begin(); p != point_list.end(); p++)
416 | fprintf(fp,"%d 1:%f 2:%f\n",p->value,p->x,p->y);
417 | fclose(fp);
418 | }
419 | }
420 | }
421 | break;
422 | case ID_BUTTON_LOAD:
423 | {
424 | char filename[1024];
425 | if(getfilename(hwnd,filename,1024,0))
426 | {
427 | FILE *fp = fopen(filename,"r");
428 | if(fp)
429 | {
430 | clear_all();
431 | char buf[4096];
432 | while(fgets(buf,sizeof(buf),fp))
433 | {
434 | int v;
435 | double x,y;
436 | if(sscanf(buf,"%d%*d:%lf%*d:%lf",&v,&x,&y)!=3)
437 | break;
438 | point p = {x,y,v};
439 | point_list.push_back(p);
440 | }
441 | fclose(fp);
442 | draw_all_points();
443 | }
444 | }
445 | }
446 | break;
447 | }
448 | }
449 | return 0;
450 | case WM_DESTROY:
451 | PostQuitMessage(0);
452 | return 0;
453 | }
454 |
455 | return DefWindowProc(hwnd, iMsg, wParam, lParam);
456 | }
457 |
--------------------------------------------------------------------------------
/svm.def:
--------------------------------------------------------------------------------
1 | LIBRARY libsvm
2 | EXPORTS
3 | svm_train @1
4 | svm_cross_validation @2
5 | svm_save_model @3
6 | svm_load_model @4
7 | svm_get_svm_type @5
8 | svm_get_nr_class @6
9 | svm_get_labels @7
10 | svm_get_svr_probability @8
11 | svm_predict_values @9
12 | svm_predict @10
13 | svm_predict_probability @11
14 | svm_free_model_content @12
15 | svm_free_and_destroy_model @13
16 | svm_destroy_param @14
17 | svm_check_parameter @15
18 | svm_check_probability_model @16
19 | svm_set_print_string_function @17
20 |
--------------------------------------------------------------------------------
/svm.h:
--------------------------------------------------------------------------------
1 | #ifndef _LIBSVM_H
2 | #define _LIBSVM_H
3 |
4 | #define LIBSVM_VERSION 310
5 |
6 | #define USEWSVM
7 |
8 | #ifdef USEWSVM
9 | #include "MetaRecognition.h"
10 | #endif
11 |
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 |
17 | extern int libsvm_version;
18 |
19 | struct svm_node{
20 | int index;
21 | double value;
22 | };
23 |
24 | struct svm_problem{
25 | int l;
26 | double *y;
27 | struct svm_node **x;
28 | int nr_classes;
29 | int *labels;
30 | };
31 |
32 |
33 | typedef enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR, OPENSET_OC, OPENSET_PAIR, OPENSET_BIN, ONE_VS_REST_WSVM, ONE_WSVM, PI_SVM} svm_type_t; /* svm_type */
34 | typedef enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED } kernel_t; /* kernel_type */
35 |
36 | typedef enum {OPT_PRECISION, OPT_RECALL, OPT_FMEASURE, OPT_HINGE, OPT_BALANCEDRISK} openset_optimization_t;
37 |
38 |
39 |
40 | struct svm_parameter{
41 | int svm_type;
42 | int kernel_type;
43 | int do_open; /* do we want to do open-set expansion of base kernel */
44 | int degree; /* for poly */
45 | double gamma; /* for poly/rbf/sigmoid */
46 | double coef0; /* for poly/sigmoid */
47 | /* these are for training only */
48 | double cache_size; /* in MB */
49 | double eps; /* stopping criteria */
50 | double C; /* for C_SVC, EPSILON_SVR and NU_SVR */
51 | int nr_weight; /* for C_SVC */
52 | int nr_fold; /* for cross-validation in training */
53 | int cross_validation; /* for cross-validation */
54 | int *weight_label; /* for C_SVC */
55 | double* weight; /* for C_SVC */
56 | double nu; /* for NU_SVC, ONE_CLASS, and NU_SVR */
57 | double p; /* for EPSILON_SVR */
58 | int shrinking; /* use the shrinking heuristics */
59 | int probability; /* do probability estimates */
60 | bool neg_labels; /* do we consider negative class labels (like -1) as a label for openset, or just negative.. default is false */
61 | bool exaustive_open; /* do we do exaustive optimization for openset.. default is false */
62 | openset_optimization_t optimize; /* choice of what to optimize */
63 | double beta; /* for use in f-measure optimization */
64 | double near_preasure, far_preasure; /* for openset risk preasures */
65 | double openset_min_probability; /* for WSVM openset, what is minimum probability to consider positive */
66 | double openset_min_probability_one_wsvm; /* for WSVM openset, what is minimum probability to consider positive for one class wsvm */
67 | FILE* vfile; /* for logging verbose stuff during debugging */
68 | int rejectedID; /* id for rejected classes (-99999 is the default) */
69 | double cap_cost; /* for C_SVC, EPSILON_SVR and NU_SVR */
70 | double cap_gamma; /* for poly/rbf/sigmoid */
71 | };
72 |
73 | //
74 | // svm_model
75 | //
76 | struct svm_model{
77 | struct svm_parameter param; /* parameter */
78 | int nr_class; /* number of classes, = 2 in regression/one class svm */
79 | int l; /* total #SV */
80 | struct svm_node **SV; /* SVs (SV[l]) */
81 | double **sv_coef; /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
82 | double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */
83 | double *probA; /* pariwise probability information */
84 | double *probB;
85 | int openset_dim; /* dimension of data for 1-vs-set models, if open_set, wsvm or open_bset (5,6,7) then openset_dim=k, if open_pair then its k*(k-1)/2*/
86 | double *alpha, *omega; /* planes offsets for 1-vs-set alpha[openset_dim], omega[openset_dim] */
87 | //double *wbltrans,*wblshape,*wblscale; /* weibul parms for wsvm all of dimension [openset_dim] */
88 | #ifdef USEWSVM
89 | MetaRecognition *MRpos_one_vs_all, *MRcomp_one_vs_all; //MetaRecognition Objects for positive (inclass) and complement classifiers for 1-vs-all
90 | MetaRecognition *MRpos_one_class; //MetaRecognition Objects for positive (inclass) one-class
91 | #endif
92 | /* for classification only */
93 |
94 | int *label; /* label of each class (label[k]) */
95 | int *nSV; /* number of SVs for each class (nSV[k]) */
96 | /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
97 | /* XXX */
98 | int free_sv; /* 1 if svm_model is created by svm_load_model and needs to free its memory*/
99 | /* 0 if svm_model is created by svm_train */
100 | };
101 |
102 | struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
103 | void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
104 | void svm_cross_validation_wsvm(const struct svm_problem *prob, const struct svm_parameter *param,const struct svm_problem *prob_one_wsvm, const struct svm_parameter *param_one_wsvm, int nr_fold, double *target);
105 |
106 | int svm_save_model(const char *model_file_name, const struct svm_model *model);
107 | struct svm_model *svm_load_model(const char *model_file_name);
108 |
109 | int svm_get_svm_type(const struct svm_model *model);
110 | int svm_get_nr_class(const struct svm_model *model);
111 | void svm_get_labels(const struct svm_model *model, int *label);
112 | double svm_get_svr_probability(const struct svm_model *model);
113 | double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
114 | double svm_predict_values_extended(const struct svm_model *model, const struct svm_node *x,
115 | double*& dec_values, double **&scores, int*& vote);
116 | double svm_predict_values_extended_plus_one_wsvm(const struct svm_model *model,const struct svm_model *model_one_wsvm, const struct svm_node *x,
117 | double*& dec_values_wsvm,double*& dec_values_one_wsvm, double **&scores, int*& vote);
118 |
119 | double svm_predict(const struct svm_model *model, const struct svm_node *x);
120 | double svm_predict_extended(const struct svm_model *model, const struct svm_node *x,
121 | double **&scores, int *&vote);
122 | double svm_predict_extended_plus_one_wsvm(const struct svm_model *model,const struct svm_model *model_one_wsvm, const struct svm_node *x,
123 | double **&scores, int *&vote);
124 | double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
125 |
126 | void svm_free_model_content(struct svm_model *model_ptr);
127 | void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
128 | void svm_destroy_param(struct svm_parameter *param);
129 |
130 | const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
131 | int svm_check_probability_model(const struct svm_model *model);
132 |
133 | void svm_set_print_string_function(void (*print_func)(const char *));
134 |
135 | typedef unsigned long ulong;
136 | #ifdef __cplusplus
137 | }
138 | #endif
139 |
140 | #endif /* _LIBSVM_H */
141 |
--------------------------------------------------------------------------------
/tools/README:
--------------------------------------------------------------------------------
1 | This directory includes some useful codes:
2 |
3 | 1. subset selection tools.
4 | 2. parameter selection tools.
5 | 3. LIBSVM format checking tools
6 |
7 | Part I: Subset selection tools
8 |
9 | Introduction
10 | ============
11 |
12 | Training large data is time consuming. Sometimes one should work on a
13 | smaller subset first. The python script subset.py randomly selects a
14 | specified number of samples. For classification data, we provide a
15 | stratified selection to ensure the same class distribution in the
16 | subset.
17 |
18 | Usage: subset.py [options] dataset number [output1] [output2]
19 |
20 | This script selects a subset of the given data set.
21 |
22 | options:
23 | -s method : method of selection (default 0)
24 | 0 -- stratified selection (classification only)
25 | 1 -- random selection
26 |
27 | output1 : the subset (optional)
28 | output2 : the rest of data (optional)
29 |
30 | If output1 is omitted, the subset will be printed on the screen.
31 |
32 | Example
33 | =======
34 |
35 | > python subset.py heart_scale 100 file1 file2
36 |
37 | From heart_scale 100 samples are randomly selected and stored in
38 | file1. All remaining instances are stored in file2.
39 |
40 |
41 | Part II: Parameter Selection Tools
42 |
43 | Introduction
44 | ============
45 |
46 | grid.py is a parameter selection tool for C-SVM classification using
47 | the RBF (radial basis function) kernel. It uses cross validation (CV)
48 | technique to estimate the accuracy of each parameter combination in
49 | the specified range and helps you to decide the best parameters for
50 | your problem.
51 |
52 | grid.py directly executes libsvm binaries (so no python binding is needed)
53 | for cross validation and then draw contour of CV accuracy using gnuplot.
54 | You must have libsvm and gnuplot installed before using it. The package
55 | gnuplot is available at http://www.gnuplot.info/
56 |
57 | On Mac OSX, the precompiled gnuplot file needs the library Aquarterm,
58 | which thus must be installed as well. In addition, this version of
59 | gnuplot does not support png, so you need to change "set term png
60 | transparent small" and use other image formats. For example, you may
61 | have "set term pbm small color".
62 |
63 | Usage: grid.py [-log2c begin,end,step] [-log2g begin,end,step] [-v fold]
64 | [-svmtrain pathname] [-gnuplot pathname] [-out pathname] [-png pathname]
65 | [additional parameters for svm-train] dataset
66 |
67 | The program conducts v-fold cross validation using parameter C (and gamma)
68 | = 2^begin, 2^(begin+step), ..., 2^end.
69 |
70 | You can specify where the libsvm executable and gnuplot are using the
71 | -svmtrain and -gnuplot parameters.
72 |
73 | For windows users, please use pgnuplot.exe. If you are using gnuplot
74 | 3.7.1, please upgrade to version 3.7.3 or higher. The version 3.7.1
75 | has a bug. If you use cygwin on windows, please use gunplot-x11.
76 |
77 | Example
78 | =======
79 |
80 | > python grid.py -log2c -5,5,1 -log2g -4,0,1 -v 5 -m 300 heart_scale
81 |
82 | Users (in particular MS Windows users) may need to specify the path of
83 | executable files. You can either change paths in the beginning of
84 | grid.py or specify them in the command line. For example,
85 |
86 | > grid.py -log2c -5,5,1 -svmtrain c:\libsvm\windows\svm-train.exe -gnuplot c:\tmp\gnuplot\bin\pgnuplot.exe -v 10 heart_scale
87 |
88 | Output: two files
89 | dataset.png: the CV accuracy contour plot generated by gnuplot
90 | dataset.out: the CV accuracy at each (log2(C),log2(gamma))
91 |
92 | Parallel grid search
93 | ====================
94 |
95 | You can conduct a parallel grid search by dispatching jobs to a
96 | cluster of computers which share the same file system. First, you add
97 | machine names in grid.py:
98 |
99 | ssh_workers = ["linux1", "linux5", "linux5"]
100 |
101 | and then setup your ssh so that the authentication works without
102 | asking a password.
103 |
104 | The same machine (e.g., linux5 here) can be listed more than once if
105 | it has multiple CPUs or has more RAM. If the local machine is the
106 | best, you can also enlarge the nr_local_worker. For example:
107 |
108 | nr_local_worker = 2
109 |
110 | Example:
111 |
112 | > python grid.py heart_scale
113 | [local] -1 -1 78.8889 (best c=0.5, g=0.5, rate=78.8889)
114 | [linux5] -1 -7 83.3333 (best c=0.5, g=0.0078125, rate=83.3333)
115 | [linux5] 5 -1 77.037 (best c=0.5, g=0.0078125, rate=83.3333)
116 | [linux1] 5 -7 83.3333 (best c=0.5, g=0.0078125, rate=83.3333)
117 | .
118 | .
119 | .
120 |
121 | If -log2c, -log2g, or -v is not specified, default values are used.
122 |
123 | If your system uses telnet instead of ssh, you list the computer names
124 | in telnet_workers.
125 |
126 | Part III: LIBSVM format checking tools
127 |
128 | Introduction
129 | ============
130 |
131 | `svm-train' conducts only a simple check of the input data. To do a
132 | detailed check, we provide a python script `checkdata.py.'
133 |
134 | Usage: checkdata.py dataset
135 |
136 | Exit status (returned value): 1 if there are errors, 0 otherwise.
137 |
138 | This tool is written by Rong-En Fan at National Taiwan University.
139 |
140 | Example
141 | =======
142 |
143 | > cat bad_data
144 | 1 3:1 2:4
145 | > python checkdata.py bad_data
146 | line 1: feature indices must be in an ascending order, previous/current features 3:1 2:4
147 | Found 1 lines with error.
148 |
149 |
150 |
--------------------------------------------------------------------------------
/tools/checkdata.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | #
4 | # A format checker for LIBSVM
5 | #
6 |
7 | #
8 | # Copyright (c) 2007, Rong-En Fan
9 | #
10 | # All rights reserved.
11 | #
12 | # This program is distributed under the same license of the LIBSVM package.
13 | #
14 |
15 | from sys import argv, exit
16 | import os.path
17 |
18 | def err(line_no, msg):
19 | print("line {0}: {1}".format(line_no, msg))
20 |
21 | # works like float() but does not accept nan and inf
22 | def my_float(x):
23 | if x.lower().find("nan") != -1 or x.lower().find("inf") != -1:
24 | raise ValueError
25 |
26 | return float(x)
27 |
28 | def main():
29 | if len(argv) != 2:
30 | print("Usage: {0} dataset".format(argv[0]))
31 | exit(1)
32 |
33 | dataset = argv[1]
34 |
35 | if not os.path.exists(dataset):
36 | print("dataset {0} not found".format(dataset))
37 | exit(1)
38 |
39 | line_no = 1
40 | error_line_count = 0
41 | for line in open(dataset, 'r'):
42 | line_error = False
43 |
44 | # each line must end with a newline character
45 | if line[-1] != '\n':
46 | err(line_no, "missing a newline character in the end")
47 | line_error = True
48 |
49 | nodes = line.split()
50 |
51 | # check label
52 | try:
53 | label = nodes.pop(0)
54 |
55 | if label.find(',') != -1:
56 | # multi-label format
57 | try:
58 | for l in label.split(','):
59 | l = my_float(l)
60 | except:
61 | err(line_no, "label {0} is not a valid multi-label form".format(label))
62 | line_error = True
63 | else:
64 | try:
65 | label = my_float(label)
66 | except:
67 | err(line_no, "label {0} is not a number".format(label))
68 | line_error = True
69 | except:
70 | err(line_no, "missing label, perhaps an empty line?")
71 | line_error = True
72 |
73 | # check features
74 | prev_index = -1
75 | for i in range(len(nodes)):
76 | try:
77 | (index, value) = nodes[i].split(':')
78 |
79 | index = int(index)
80 | value = my_float(value)
81 |
82 | # precomputed kernel's index starts from 0 and LIBSVM
83 | # checks it. Hence, don't treat index 0 as an error.
84 | if index < 0:
85 | err(line_no, "feature index must be positive; wrong feature {0}".format(nodes[i]))
86 | line_error = True
87 | elif index < prev_index:
88 | err(line_no, "feature indices must be in an ascending order, previous/current features {0} {1}".format(nodes[i-1], nodes[i]))
89 | line_error = True
90 | prev_index = index
91 | except:
92 | err(line_no, "feature '{0}' not an : pair, integer, real number ".format(nodes[i]))
93 | line_error = True
94 |
95 | line_no += 1
96 |
97 | if line_error:
98 | error_line_count += 1
99 |
100 | if error_line_count > 0:
101 | print("Found {0} lines with error.".format(error_line_count))
102 | return 1
103 | else:
104 | print("No error.")
105 | return 0
106 |
107 | if __name__ == "__main__":
108 | exit(main())
109 |
--------------------------------------------------------------------------------
/tools/easy.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 | import os
5 | from subprocess import *
6 |
7 | if len(sys.argv) <= 1:
8 | print('Usage: {0} training_file [testing_file]'.format(sys.argv[0]))
9 | raise SystemExit
10 |
11 | # svm, grid, and gnuplot executable files
12 |
13 | is_win32 = (sys.platform == 'win32')
14 | if not is_win32:
15 | svmscale_exe = "../svm-scale"
16 | svmtrain_exe = "../svm-train"
17 | svmpredict_exe = "../svm-predict"
18 | grid_py = "./grid.py"
19 | gnuplot_exe = "/usr/bin/gnuplot"
20 | else:
21 | # example for windows
22 | svmscale_exe = r"..\windows\svm-scale.exe"
23 | svmtrain_exe = r"..\windows\svm-train.exe"
24 | svmpredict_exe = r"..\windows\svm-predict.exe"
25 | gnuplot_exe = r"c:\tmp\gnuplot\bin\pgnuplot.exe"
26 | grid_py = r".\grid.py"
27 |
28 | assert os.path.exists(svmscale_exe),"svm-scale executable not found"
29 | assert os.path.exists(svmtrain_exe),"svm-train executable not found"
30 | assert os.path.exists(svmpredict_exe),"svm-predict executable not found"
31 | assert os.path.exists(gnuplot_exe),"gnuplot executable not found"
32 | assert os.path.exists(grid_py),"grid.py not found"
33 |
34 | train_pathname = sys.argv[1]
35 | assert os.path.exists(train_pathname),"training file not found"
36 | file_name = os.path.split(train_pathname)[1]
37 | scaled_file = file_name + ".scale"
38 | model_file = file_name + ".model"
39 | range_file = file_name + ".range"
40 |
41 | if len(sys.argv) > 2:
42 | test_pathname = sys.argv[2]
43 | file_name = os.path.split(test_pathname)[1]
44 | assert os.path.exists(test_pathname),"testing file not found"
45 | scaled_test_file = file_name + ".scale"
46 | predict_test_file = file_name + ".predict"
47 |
48 | cmd = '{0} -s "{1}" "{2}" > "{3}"'.format(svmscale_exe, range_file, train_pathname, scaled_file)
49 | print('Scaling training data...')
50 | Popen(cmd, shell = True, stdout = PIPE).communicate()
51 |
52 | cmd = '{0} -svmtrain "{1}" -gnuplot "{2}" "{3}"'.format(grid_py, svmtrain_exe, gnuplot_exe, scaled_file)
53 | print('Cross validation...')
54 | f = Popen(cmd, shell = True, stdout = PIPE).stdout
55 |
56 | line = ''
57 | while True:
58 | last_line = line
59 | line = f.readline()
60 | if not line: break
61 | c,g,rate = map(float,last_line.split())
62 |
63 | print('Best c={0}, g={1} CV rate={2}'.format(c,g,rate))
64 |
65 | cmd = '{0} -c {1} -g {2} "{3}" "{4}"'.format(svmtrain_exe,c,g,scaled_file,model_file)
66 | print('Training...')
67 | Popen(cmd, shell = True, stdout = PIPE).communicate()
68 |
69 | print('Output model: {0}'.format(model_file))
70 | if len(sys.argv) > 2:
71 | cmd = '{0} -r "{1}" "{2}" > "{3}"'.format(svmscale_exe, range_file, test_pathname, scaled_test_file)
72 | print('Scaling testing data...')
73 | Popen(cmd, shell = True, stdout = PIPE).communicate()
74 |
75 | cmd = '{0} "{1}" "{2}" "{3}"'.format(svmpredict_exe, scaled_test_file, model_file, predict_test_file)
76 | print('Testing...')
77 | Popen(cmd, shell = True).communicate()
78 |
79 | print('Output prediction: {0}'.format(predict_test_file))
80 |
--------------------------------------------------------------------------------
/tools/subset.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from sys import argv, exit, stdout, stderr
3 | from random import randint
4 |
5 | method = 0
6 | global n
7 | global dataset_filename
8 | subset_filename = ""
9 | rest_filename = ""
10 |
11 | def exit_with_help():
12 | print("""\
13 | Usage: {0} [options] dataset number [output1] [output2]
14 |
15 | This script selects a subset of the given dataset.
16 |
17 | options:
18 | -s method : method of selection (default 0)
19 | 0 -- stratified selection (classification only)
20 | 1 -- random selection
21 |
22 | output1 : the subset (optional)
23 | output2 : rest of the data (optional)
24 | If output1 is omitted, the subset will be printed on the screen.""".format(argv[0]))
25 | exit(1)
26 |
27 | def process_options():
28 | global method, n
29 | global dataset_filename, subset_filename, rest_filename
30 |
31 | argc = len(argv)
32 | if argc < 3:
33 | exit_with_help()
34 |
35 | i = 1
36 | while i < len(argv):
37 | if argv[i][0] != "-":
38 | break
39 | if argv[i] == "-s":
40 | i = i + 1
41 | method = int(argv[i])
42 | if method < 0 or method > 1:
43 | print("Unknown selection method {0}".format(method))
44 | exit_with_help()
45 | i = i + 1
46 |
47 | dataset_filename = argv[i]
48 | n = int(argv[i+1])
49 | if i+2 < argc:
50 | subset_filename = argv[i+2]
51 | if i+3 < argc:
52 | rest_filename = argv[i+3]
53 |
54 | def main():
55 | class Label:
56 | def __init__(self, label, index, selected):
57 | self.label = label
58 | self.index = index
59 | self.selected = selected
60 |
61 | process_options()
62 |
63 | # get labels
64 | i = 0
65 | labels = []
66 | f = open(dataset_filename, 'r')
67 | for line in f:
68 | labels.append(Label(float((line.split())[0]), i, 0))
69 | i = i + 1
70 | f.close()
71 | l = i
72 |
73 | # determine where to output
74 | if subset_filename != "":
75 | file1 = open(subset_filename, 'w')
76 | else:
77 | file1 = stdout
78 | split = 0
79 | if rest_filename != "":
80 | split = 1
81 | file2 = open(rest_filename, 'w')
82 |
83 | # select the subset
84 | warning = 0
85 | if method == 0: # stratified
86 | labels.sort(key = lambda x: x.label)
87 |
88 | label_end = labels[l-1].label + 1
89 | labels.append(Label(label_end, l, 0))
90 |
91 | begin = 0
92 | label = labels[begin].label
93 | for i in range(l+1):
94 | new_label = labels[i].label
95 | if new_label != label:
96 | nr_class = i - begin
97 | k = i*n//l - begin*n//l
98 | # at least one instance per class
99 | if k == 0:
100 | k = 1
101 | warning = warning + 1
102 | for j in range(nr_class):
103 | if randint(0, nr_class-j-1) < k:
104 | labels[begin+j].selected = 1
105 | k = k - 1
106 | begin = i
107 | label = new_label
108 | elif method == 1: # random
109 | k = n
110 | for i in range(l):
111 | if randint(0,l-i-1) < k:
112 | labels[i].selected = 1
113 | k = k - 1
114 | i = i + 1
115 |
116 | # output
117 | i = 0
118 | if method == 0:
119 | labels.sort(key = lambda x: int(x.index))
120 |
121 | f = open(dataset_filename, 'r')
122 | for line in f:
123 | if labels[i].selected == 1:
124 | file1.write(line)
125 | else:
126 | if split == 1:
127 | file2.write(line)
128 | i = i + 1
129 |
130 | if warning > 0:
131 | stderr.write("""\
132 | Warning:
133 | 1. You may have regression data. Please use -s 1.
134 | 2. Classification data unbalanced or too small. We select at least 1 per class.
135 | The subset thus contains {0} instances.
136 | """.format(n+warning))
137 |
138 | # cleanup
139 | f.close()
140 |
141 | file1.close()
142 |
143 | if split == 1:
144 | file2.close()
145 |
146 | main()
147 |
--------------------------------------------------------------------------------