Example #1
0
func SaveLibSVMDataset(path string, set data.Dataset) {
	log.Print("保存数据集到libsvm格式文件", path)

	f, err := os.Create(path)
	defer f.Close()
	if err != nil {
		log.Fatalf("无法打开文件\"%v\",错误提示:%v\n", path, err)
	}
	w := bufio.NewWriter(f)
	defer w.Flush()

	iter := set.CreateIterator()
	iter.Start()
	for !iter.End() {
		instance := iter.GetInstance()
		if instance.Output.LabelString == "" {
			fmt.Fprintf(w, "%d ", instance.Output.Label)
		} else {
			fmt.Fprintf(w, "%s ", instance.Output.LabelString)
		}
		for _, k := range instance.Features.Keys() {
			// 跳过第0个特征,因为它始终是1
			if k == 0 {
				continue
			}

			if instance.Features.Get(k) != 0 {
				// libsvm格式的特征从1开始
				fmt.Fprintf(w, "%d:%s ", k, strconv.FormatFloat(instance.Features.Get(k), 'f', -1, 64))
			}
		}
		fmt.Fprint(w, "\n")
		iter.Next()
	}
}
Example #2
0
File: rbm.go Project: sguzwf/mlf
func (rbm *RBM) feeder(set data.Dataset, ch chan *data.Instance) {
	iter := set.CreateIterator()
	iter.Start()
	for it := 0; it < set.NumInstances(); it++ {
		instance := iter.GetInstance()
		ch <- instance
		iter.Next()
	}
}
Example #3
0
// 输出的度量名字为 "confusion:M/N" 其中M为真实标注,N为预测标注
func (e *ConfusionMatrixEvaluator) Evaluate(m supervised.Model, set data.Dataset) (result Evaluation) {
	result.Metrics = make(map[string]float64)
	iter := set.CreateIterator()
	iter.Start()
	for !iter.End() {
		instance := iter.GetInstance()
		out := m.Predict(instance)
		name := fmt.Sprintf("confusion:%d/%d", instance.Output.Label, out.Label)
		result.Metrics[name]++
		iter.Next()
	}
	return
}
Example #4
0
func (e *PREvaluator) Evaluate(m supervised.Model, set data.Dataset) (result Evaluation) {
	tp := 0 // true-positive
	tn := 0 // true-negative
	fp := 0 // false-positive
	fn := 0 // false-negative

	iter := set.CreateIterator()
	iter.Start()
	for !iter.End() {
		instance := iter.GetInstance()
		if instance.Output.Label > 2 {
			log.Fatal("调用PREvaluator但不是二分类问题")
		}

		out := m.Predict(instance)
		if out.Label == 0 {
			if instance.Output.Label == 0 {
				tn++
			} else {
				fn++
			}
		} else {
			if instance.Output.Label == 0 {
				fp++
			} else {
				tp++
			}
		}
		iter.Next()
	}

	result.Metrics = make(map[string]float64)
	result.Metrics["precision"] = float64(tp) / float64(tp+fp)
	result.Metrics["recall"] = float64(tp) / float64(tp+fn)
	result.Metrics["tp"] = float64(tp)
	result.Metrics["fp"] = float64(fp)
	result.Metrics["tn"] = float64(tn)
	result.Metrics["fn"] = float64(fn)
	result.Metrics["fscore"] =
		2 * result.Metrics["precision"] * result.Metrics["recall"] / (result.Metrics["precision"] + result.Metrics["recall"])

	return
}
Example #5
0
func (e *AccuracyEvaluator) Evaluate(m supervised.Model, set data.Dataset) (result Evaluation) {
	correctPrediction := 0
	totalPrediction := 0

	iter := set.CreateIterator()
	iter.Start()
	for !iter.End() {
		instance := iter.GetInstance()
		out := m.Predict(instance)
		if instance.Output.Label == out.Label {
			correctPrediction++
		}
		totalPrediction++
		iter.Next()
	}

	result.Metrics = make(map[string]float64)
	result.Metrics["accuracy"] = float64(correctPrediction) / float64(totalPrediction)

	return
}
Example #6
0
File: gd.go Project: hycxa/mlf
func (opt *gdOptimizer) OptimizeWeights(
	weights *util.Matrix, derivative_func ComputeInstanceDerivativeFunc, set data.Dataset) {
	// 偏导数向量
	derivative := weights.Populate()

	// 学习率计算器
	learningRate := NewLearningRate(opt.options)

	// 优化循环
	iterator := set.CreateIterator()
	step := 0
	var learning_rate float64
	convergingSteps := 0
	oldWeights := weights.Populate()
	weightsDelta := weights.Populate()
	instanceDerivative := weights.Populate()
	log.Print("开始梯度递降优化")
	for {
		if opt.options.MaxIterations > 0 && step >= opt.options.MaxIterations {
			break
		}
		step++

		// 每次遍历样本前对偏导数向量清零
		derivative.Clear()

		// 遍历所有样本,计算偏导数向量并累加
		iterator.Start()
		instancesProcessed := 0
		for !iterator.End() {
			instance := iterator.GetInstance()
			derivative_func(weights, instance, instanceDerivative)
			derivative.Increment(instanceDerivative, 1.0/float64(set.NumInstances()))
			iterator.Next()
			instancesProcessed++

			if opt.options.GDBatchSize > 0 && instancesProcessed >= opt.options.GDBatchSize {
				// 添加正则化项
				derivative.Increment(ComputeRegularization(weights, opt.options),
					float64(instancesProcessed)/(float64(set.NumInstances())*float64(set.NumInstances())))

				// 计算特征权重的增量
				delta := opt.GetDeltaX(weights, derivative)

				// 根据学习率更新权重
				learning_rate = learningRate.ComputeLearningRate(delta)
				weights.Increment(delta, learning_rate)

				// 重置
				derivative.Clear()
				instancesProcessed = 0
			}
		}

		if instancesProcessed > 0 {
			// 处理剩余的样本
			derivative.Increment(ComputeRegularization(weights, opt.options),
				float64(instancesProcessed)/(float64(set.NumInstances())*float64(set.NumInstances())))
			delta := opt.GetDeltaX(weights, derivative)
			learning_rate = learningRate.ComputeLearningRate(delta)
			weights.Increment(delta, learning_rate)
		}

		weightsDelta.WeightedSum(weights, oldWeights, 1, -1)
		oldWeights.DeepCopy(weights)
		weightsNorm := weights.Norm()
		weightsDeltaNorm := weightsDelta.Norm()
		log.Printf("#%d |w|=%1.3g |dw|/|w|=%1.3g lr=%1.3g", step, weightsNorm, weightsDeltaNorm/weightsNorm, learning_rate)

		// 判断是否溢出
		if math.IsNaN(weightsNorm) {
			log.Fatal("优化失败:不收敛")
		}

		// 判断是否收敛
		if weightsDelta.Norm()/weights.Norm() < opt.options.ConvergingDeltaWeight {
			convergingSteps++
			if convergingSteps > opt.options.ConvergingSteps {
				log.Printf("收敛")
				break
			}
		}
	}
}
Example #7
0
func (trainer *MaxEntClassifierTrainer) Train(set data.Dataset) Model {
	// 检查训练数据是否是分类问题
	if !set.GetOptions().IsSupervisedLearning {
		log.Fatal("训练数据不是分类问题数据")
	}

	// 建立新的优化器
	optimizer := optimizer.NewOptimizer(trainer.options.Optimizer)

	// 建立特征权重向量
	featureDimension := set.GetOptions().FeatureDimension
	numLabels := set.GetOptions().NumLabels
	var weights *util.Matrix
	if set.GetOptions().FeatureIsSparse {
		weights = util.NewSparseMatrix(numLabels)
	} else {
		weights = util.NewMatrix(numLabels, featureDimension)
	}

	// 得到优化的特征权重向量
	optimizer.OptimizeWeights(weights, MaxEntComputeInstanceDerivative, set)

	classifier := new(MaxEntClassifier)
	classifier.Weights = weights
	classifier.NumLabels = numLabels
	classifier.FeatureDimension = featureDimension
	classifier.FeatureDictionary = set.GetFeatureDictionary()
	classifier.LabelDictionary = set.GetLabelDictionary()
	return classifier
}
Example #8
0
File: rbm.go Project: sguzwf/mlf
func (rbm *RBM) Train(set data.Dataset) {
	featureDimension := set.GetOptions().FeatureDimension
	visibleDim := featureDimension
	hiddenDim := rbm.options.NumHiddenUnits + 1
	log.Printf("#visible = %d, #hidden = %d", featureDimension-1, hiddenDim-1)

	// 随机化 weights
	rbm.lock.Lock()
	rbm.lock.weights = util.NewMatrix(hiddenDim, visibleDim)
	oldWeights := util.NewMatrix(hiddenDim, visibleDim)
	batchDerivative := util.NewMatrix(hiddenDim, visibleDim)
	for i := 0; i < hiddenDim; i++ {
		for j := 0; j < visibleDim; j++ {
			value := (rand.Float64()*2 - 1) * 0.01
			rbm.lock.weights.Set(i, j, value)
		}
	}
	rbm.lock.Unlock()

	// 启动工作协程
	ch := make(chan *data.Instance, rbm.options.Worker)
	out := make(chan *util.Matrix, rbm.options.Worker)
	for iWorker := 0; iWorker < rbm.options.Worker; iWorker++ {
		go rbm.derivativeWorker(ch, out, visibleDim, hiddenDim)
	}

	iteration := 0
	delta := 1.0
	for (rbm.options.MaxIter == 0 || iteration < rbm.options.MaxIter) &&
		(rbm.options.Delta == 0 || delta > rbm.options.Delta) {
		iteration++

		go rbm.feeder(set, ch)
		iBatch := 0
		batchDerivative.Clear()
		numInstances := set.NumInstances()
		for it := 0; it < numInstances; it++ {
			// 乱序读入
			derivative := <-out
			batchDerivative.Increment(derivative, rbm.options.LearningRate)
			iBatch++

			if iBatch == rbm.options.BatchSize || it == numInstances-1 {
				rbm.lock.Lock()
				rbm.lock.weights.Increment(batchDerivative, 1.0)
				rbm.lock.Unlock()
				iBatch = 0
				batchDerivative.Clear()
			}
		}

		// 统计delta和|weight|
		rbm.lock.RLock()
		weightsNorm := rbm.lock.weights.Norm()
		batchDerivative.DeepCopy(rbm.lock.weights)
		batchDerivative.Increment(oldWeights, -1.0)
		derivativeNorm := batchDerivative.Norm()
		delta = derivativeNorm / weightsNorm
		log.Printf("iter = %d, delta = %f, |weight| = %f",
			iteration, delta, weightsNorm)
		oldWeights.DeepCopy(rbm.lock.weights)
		rbm.lock.RUnlock()
	}
}
Example #9
0
File: lbfgs.go Project: sguzwf/mlf
func (opt *lbfgsOptimizer) OptimizeWeights(
	weights *util.Matrix, derivative_func ComputeInstanceDerivativeFunc, set data.Dataset) {

	// 学习率计算器
	learningRate := NewLearningRate(opt.options)

	// 偏导数向量
	derivative := weights.Populate()

	// 优化循环
	step := 0
	convergingSteps := 0
	oldWeights := weights.Populate()
	weightsDelta := weights.Populate()

	// 为各个工作协程开辟临时资源
	numLbfgsThreads := *lbfgs_threads
	if numLbfgsThreads == 0 {
		numLbfgsThreads = runtime.NumCPU()
	}
	workerSet := make([]data.Dataset, numLbfgsThreads)
	workerDerivative := make([]*util.Matrix, numLbfgsThreads)
	workerInstanceDerivative := make([]*util.Matrix, numLbfgsThreads)
	for iWorker := 0; iWorker < numLbfgsThreads; iWorker++ {
		workerBuckets := []data.SkipBucket{
			{true, iWorker},
			{false, 1},
			{true, numLbfgsThreads - 1 - iWorker},
		}
		workerSet[iWorker] = data.NewSkipDataset(set, workerBuckets)
		workerDerivative[iWorker] = weights.Populate()
		workerInstanceDerivative[iWorker] = weights.Populate()
	}

	log.Print("开始L-BFGS优化")
	for {
		if opt.options.MaxIterations > 0 && step >= opt.options.MaxIterations {
			break
		}
		step++

		// 开始工作协程
		workerChannel := make(chan int, numLbfgsThreads)
		for iWorker := 0; iWorker < numLbfgsThreads; iWorker++ {
			go func(iw int) {
				workerDerivative[iw].Clear()
				iterator := workerSet[iw].CreateIterator()
				iterator.Start()
				for !iterator.End() {
					instance := iterator.GetInstance()
					derivative_func(
						weights, instance, workerInstanceDerivative[iw])
					//					log.Print(workerInstanceDerivative[iw].GetValues(0))
					workerDerivative[iw].Increment(
						workerInstanceDerivative[iw], float64(1)/float64(set.NumInstances()))
					iterator.Next()
				}
				workerChannel <- iw
			}(iWorker)
		}

		derivative.Clear()

		// 等待工作协程结束
		for iWorker := 0; iWorker < numLbfgsThreads; iWorker++ {
			<-workerChannel
		}
		for iWorker := 0; iWorker < numLbfgsThreads; iWorker++ {
			derivative.Increment(workerDerivative[iWorker], 1)
		}

		// 添加正则化项
		derivative.Increment(ComputeRegularization(weights, opt.options), 1.0/float64(set.NumInstances()))

		// 计算特征权重的增量
		delta := opt.GetDeltaX(weights, derivative)

		// 根据学习率更新权重
		learning_rate := learningRate.ComputeLearningRate(delta)
		weights.Increment(delta, learning_rate)

		weightsDelta.WeightedSum(weights, oldWeights, 1, -1)
		oldWeights.DeepCopy(weights)
		weightsNorm := weights.Norm()
		weightsDeltaNorm := weightsDelta.Norm()
		log.Printf("#%d |dw|/|w|=%f |w|=%f lr=%1.3g", step, weightsDeltaNorm/weightsNorm, weightsNorm, learning_rate)

		// 判断是否溢出
		if math.IsNaN(weightsNorm) {
			log.Fatal("优化失败:不收敛")
		}

		// 判断是否收敛
		if weightsDeltaNorm/weightsNorm < opt.options.ConvergingDeltaWeight {
			convergingSteps++
			if convergingSteps > opt.options.ConvergingSteps {
				log.Printf("收敛")
				break
			}
		} else {
			convergingSteps = 0
		}
	}
}