我在使用Weka构建随机森林模型。我的数据存储在MySQL数据库中。我找不到直接从数据库创建Weka数据集(’Instances’对象)的方法(至少没有直接的方法),所以我查询数据库并使用以下代码将数据处理成Weka数据集(Instances):
List<MetadataRecord> metadata = acquireMetadata(); // 从数据库加载 int datasetSize = metadata.size(); int numFeatures = MetadataRecord.FEATURE_NUM; // 当前设置为14 ArrayList<Attribute> atts = new ArrayList<Attribute>(); List<Instance> instances = new ArrayList<Instance>(); for (int feature = 0; feature < numFeatures; feature++) { Attribute current = new Attribute("Attribute" + feature, feature); if (feature == 0) { for (int obj = 0; obj < datasetSize; obj++) { instances.add(new SparseInstance(numFeatures)); } } for (int obj = 0; obj < datasetSize; obj++) { MetadataRecord record = metadata.get(obj); Instance inst = instances.get(obj); switch (feature) { case 0: inst.setValue(current, record.labelId); break; case 1: inst.setValue(current, record.isSecured ? 2 : 1); break; case 2: inst.setValue(current, record.pageCount); break; // 省略了3-13的情况... } } atts.add(current); } Instances newDataset = new Instances("Metadata", atts, instances.size()); for (Instance inst : instances) { newDataset.add(inst); } newDataset.setClassIndex(0);
大部分数据都被输入为’数值型’,而我需要将一些特征(第一和第二)转换为分类型(或按照Weka的术语为“名义型”)。我尝试使用过滤器将它们转换为名义型:
NumericToNominal nomFilter = new NumericToNominal(); nomFilter.setAttributeIndicesArray(new int[] { 0, 1 }); nomFilter.setInputFormat(newDataset); newDataset = Filter.useFilter(newDataset, nomFilter);
这运作良好,但令人惊讶的是,在调试数据集时,发现一些数据丢失了!
应用过滤器前:
@attribute Attribute0 numeric@attribute Attribute1 numeric@attribute Attribute2 numeric// 省略了其他10个属性@data{0 1005,1 1,2 19,3 1123,4 7,5 25,6 0.66,7 49,8 2892.21,9 5.32,10 22.63,11 0.4,12 48.95,13 5.29}
应用过滤器后:
@attribute Attribute0 {0,2,3,4,5,6,7,9,11,12,18,22,23,24,25,35,36,39,40,45,51,56,60,67,68,69,78,79,83,84,85,88,94,98,126,127,128,1001,1003,1004,1005,1007,1008,1009,1012,1013,1017,1018,1019,1022}@attribute Attribute1 {1,2}@attribute Attribute2 numeric// 省略了其他10个属性@data{0 1005,2 19,3 1123,4 7,5 25,6 0.66,7 49,8 2892.21,9 5.32,10 22.63,11 0.4,12 48.95,13 5.29}
为什么第二个属性的值丢失了?
回答:
该特征并没有丢失,只是没有在输出中明确显示,因为它是以稀疏格式存储的。请查看ARFF文件格式说明:
稀疏ARFF文件与ARFF文件非常相似,但值为0的数据不会被明确表示。
稀疏ARFF文件具有相同的头部(即@relation和@attribute标签),但数据部分不同。不是按顺序表示每个值,像这样:
@data0, X, 0, Y, "class A"0, 0, W, 0, "class B"
而是明确指出非零属性的属性编号及其值,像这样:
@data{1 X, 3 Y, 4 "class A"}{2 W, 4 "class B"}
每个实例都用大括号包围,每个条目的格式为:其中index是属性索引(从0开始)。
请注意,稀疏实例中省略的值为0,它们不是“缺失”值!如果一个值未知,必须用问号(?)明确表示。
特别是最后一句非常重要。你的Attribute1
有两个可能的值,1和2。由于现在是名义型,值1的索引为0。而索引为0的值会被省略。
再次强调:这只是在内存中和打印到文件或屏幕上的表示方式。你的数据集的实际内容并没有改变。