// Given the individuals, perform a single "Sub-Max-Diversity" tournament of // given size. The selected individual is the least different from the average // of the provided population. func SampleSMDTournament(sample []*Individual) *Individual { // Don't perform the full procedure if only one individual if len(sample) == 1 { return sample[0].Copy().(*Individual) } // Get images of sample simgs := make([]*imgut.Image, len(sample)) for i := range sample { // TODO make sure this doesn't require a re-evaluation simgs[i] = sample[i].ImgTemp } // Compute the average image avgImage := imgut.Average(simgs) // Once the average is computed, pick a random individual b := 0 // And compute its distance from the average bdist := imgut.PixelRMSE(sample[b].ImgTemp, avgImage) // Select other players and get the best for i := range sample { // Compute distance from average dist := imgut.PixelRMSE(sample[i].ImgTemp, avgImage) // If distance increases, we are maximizing diversity if dist > bdist { bdist = dist b = i } } return sample[b].Copy().(*Individual) }
func MakeFitEdge(targetImage *imgut.Image, stats map[string]*sequence.SequenceStats) func(*imgut.Image) float64 { // Compute edge detection edgeKern := &imgut.ConvolutionMatrix{3, []float64{ 0, 1, 0, 1, -4, 1, 0, 1, 0}, } targEdge := imgut.ApplyConvolution(edgeKern, targetImage) // Function to compute RMSE rmseFit := MakeFitRMSE(targetImage) return func(indImg *imgut.Image) float64 { // Compute regular RMSE on this image rmse := rmseFit(indImg) imgEdge := imgut.ApplyConvolution(edgeKern, indImg) // Compute distance between edges edRmse := imgut.PixelRMSE(imgEdge, targEdge) // Statistics on output values if _, ok := stats["sub-fit-plain"]; !ok { stats["sub-fit-plain"] = sequence.Create() } stats["sub-fit-plain"].Observe(rmse) if _, ok := stats["sub-fit-edged"]; !ok { stats["sub-fit-edged"] = sequence.Create() } stats["sub-fit-edged"].Observe(edRmse) // Weighted fitness return rmse * edRmse } }
// Locality test func testRepr(initFunc func(maxDep int) *node.Node, mutateFunc func(float64, *node.Node), paintFunc func(*node.Node, *imgut.Image)) (avgErr, varErr float64) { // Create storage for the images indImage := imgut.Create(IMG_W, IMG_H, imgut.MODE_RGB) tmpImage := imgut.Create(IMG_W, IMG_H, imgut.MODE_RGB) // Build random individuals randomIndividuals := make([]*node.Node, N) // For each individual var totErrorSum float64 = 0 var totErrorSqr float64 = 0 for _, i := range randomIndividuals { // Initialize it i = initFunc(MAX_D) // Render it to an image (it will be garbage) indImage.Clear() paintFunc(i, indImage) // Average error for this individual var indErrorSum float64 = 0 var indErrorSqr float64 = 0 for k := 0; k < M; k++ { // Copy the individual j := i.Copy() // Mutate the individual mutateFunc(1, j) // Render it to another image tmpImage.Clear() paintFunc(j, tmpImage) // Compute distance dist := imgut.PixelRMSE(indImage, tmpImage) // Accumulate distance indErrorSum += dist indErrorSqr += dist * dist } // Compute average error indErrorAvg := indErrorSum / float64(M) // Compute variance indErrorVar := indErrorSqr/float64(M) - (indErrorAvg * indErrorAvg) fmt.Println(" Individual avg error and variance:", indErrorAvg, indErrorVar) // Accumulate error totErrorSum += indErrorAvg totErrorSqr += indErrorAvg * indErrorAvg } // Compute average error of the averages avgErr = totErrorSum / float64(N) // Compute variance of the averages varErr = totErrorSqr/float64(N) - (avgErr * avgErr) fmt.Println("Total error and var:", avgErr, varErr) return }
func fitnessRMSEImage(ind, targ *imgut.Image) float64 { return imgut.PixelRMSE(ind, targ) }
func (s *Solution) Fitness() float64 { // Draw the individual rr.Draw(s.Node, s.ImgTemp) // Compute RMSE return imgut.PixelRMSE(s.ImgTemp, s.Conf.ImgTarget) }