LDA训练方法介绍

本节使用Linear Discriminant Analysis (LDA)展示shark基本用法
LDA可以理解为logistic regression的升级版,可以处理multiple classes
数据集使用植物分类iris.csv数据集,Iris-setosa = 0,Iris-versicolor = 1,Iris-virginica = 2

#include <iostream>
#include <shark/Data/Csv.h>
#include <shark/Algorithms/Trainers/LDA.h>
#include <shark/ObjectiveFunctions/Loss/ZeroOneLoss.h>
using namespace shark;
using std::cout;
using std::endl;

int main(int argc, const char * argv[])
{
    try
    {
        //1.准备数据
        //shark的好用之处在于对数据集本身提供了较好的抽象,有Data, UnlabeledData和LabeledData三种。Data即纯数据,unlabeled语义上用于unsuperivsed learning,labeled用于superivsed learning
        ClassificationDataset dataTrain;            //类型为LabeledData<RealVector,unsigned int>,即feature是real,label是uint。shark里所有标签都应该是uint,从0开始递增
        importCSV(dataTrain, "iris.csv", LAST_COLUMN);      //读取csv到数据集,LAST_COLUMN指定标签在末列。分隔符默认为',',虽然可以换但是实际测试时发现','以外的解析会错误
        dataTrain.shuffle();
        auto dataTest = splitAtElement(dataTrain, 0.8*dataTrain.numberOfElements());    //将全部数据切分为训练集(80%)和测试集(20%)两部分
        //2.模型和训练(shark将模型和算法区分开来)
        LinearClassifier<> classifier;      //LDA属于线性算法所以定义一个线性模型
        LDA lda;        //LDA算法,即trainer
        lda.train(classifier, dataTrain);       //通常来说训练需要model, objective function, optimizer以及迭代直到找到optimal result,trainer隐藏了这些细节让我们直接得到最终结果(当然也可以自己手动写不用trainer)
        //3.评估(该阶段一般是定义loss function然后对比预测和实际标签来计算正确率)
        ZeroOneLoss<> loss;                 //使用最简单的ZeroOneLossFunction,即预测正确为0,错误为1
        Data<unsigned int> predictions = classifier(dataTest.inputs());     //模型重载了()来进行预测,输入是许多instances,返回许多标签
        double error = loss(dataTest.labels(), predictions);     //loss function重载了(),给定正确标签和预测标签来计算正确率
        cout << "error rate: " << error << endl;
        //4.预测(单个instance)
        RealVector points = {6.3, 3.0, 4.7, 1.1};
        cout << classifier(points) << endl;     //输入是单个instance则返回一个标签(这里即uint)
    }
    catch (const std::exception &e)
    {
        cout << e.what() << endl;
    }
    return 0;
}