public void StartRERA(DaneshWindow gen, int num) { danesh = gen; numberOfAttemptsRandom = num; // DrawRandomERGraph(); LastERA = SampleExpressiveRangeRandomly(num, gen); }
public float Evaluate(object[] arr, float samples, DaneshWindow dan) { for (int i = 0; i < c_params.Count; i++) { c_params[i].field.SetValue(c_params[i].owner, arr[i]); } float totalScore = 0f; for (int att = 0; att < samples; att++) { object map = dan.GenerateContent(); float score = 0f; //Obtain a metric reading for every targeted metric for (int i = 0; i < c_metrics.Count; i++) { float val = (float)dan.GetMetric(c_metrics[i], new object[] { map }); score += 1 - Mathf.Abs(val - c_targets[i]); } //Get a score by averaging them totalScore += score / c_metrics.Count; } return(totalScore / (float)samples); }
List <List <float> > SampleExpressiveRangeRandomly(int totalAttempts, DaneshWindow gen) { float progressBar = 0f; EditorUtility.DisplayProgressBar("Computing Randomised Expressive Range Histogram", "Working...", progressBar); List <List <float> > res = new List <List <float> >(); /* * Current: * eraSample[metric1][metric2] = object[,] of samples representing the histogram * Lot of data duplication here, not the most efficient way to do it */ eraSamples = new List <List <object[, ]> >(); for (int i = 0; i < danesh.metricList.Count; i++) { List <object[, ]> secondmetric = new List <object[, ]>(); for (int j = 0; j < danesh.metricList.Count; j++) { object[,] sampleH = new object[100, 100]; secondmetric.Add(sampleH); } eraSamples.Add(secondmetric); } for (int att = 0; att < totalAttempts; att++) { //Randomly parameterise the generator foreach (GeneratorParameter p in gen.parameterList) { p.RandomiseValue(); } object map = danesh.GenerateContent(); List <float> nums = new List <float>(); for (int i = 0; i < danesh.metricList.Count; i++) { float score = (float)danesh.GetMetric(i, new object[] { map }); nums.Add(score); } //Update the samples list for (int i = 0; i < nums.Count; i++) { int index1 = (int)Mathf.Round(nums[i] * 100f); if (index1 < 0) { index1 = 0; } if (index1 > 99) { index1 = 99; } for (int j = 0; j < nums.Count; j++) { int index2 = (int)Mathf.Round(nums[j] * 100f); if (index2 < 0) { index2 = 0; } if (index2 > 99) { index2 = 99; } eraSamples[i][j][index1, index2] = map; } } res.Add(nums); EditorUtility.DisplayProgressBar("Computing Randomised Expressive Range Histogram", "Evaluating random expressive range... " + (100 * (float)att / (float)totalAttempts).ToString("F0") + " percent complete", (float)att / (float)totalAttempts); } EditorUtility.ClearProgressBar(); return(res); }
public void StartERA(DaneshWindow gen, int num) { danesh = gen; numberOfAttempts = num; LastERA = SampleExpressiveRange(num); }
public List <GeneratorParameter> FindParameters(DaneshWindow d, MonoBehaviour b) { // Debug.Log("Searching for parameters... "+d.metricList.Count+" metrics found."); List <GeneratorParameter> res = new List <GeneratorParameter>(); //Collect a control sample set List <float> metricAverages = new List <float>(); List <float[]> stdev_samples = new List <float[]>(); List <float> stdev = new List <float>(); for (int i = 0; i < d.metricList.Count; i++) { metricAverages.Add(0); stdev_samples.Add(new float[numSamples]); } for (int s = 0; s < numSamples; s++) { object output = d.GenerateContent(); for (int i = 0; i < d.metricList.Count; i++) { GeneratorMetric m = d.metricList[i]; float sc = (float)m.method.Invoke(null, new object[] { output }); metricAverages[i] += sc; stdev_samples[i][s] = sc; } } //Calculate averages and standard deviation for (int i = 0; i < d.metricList.Count; i++) { metricAverages[i] = metricAverages[i] / numSamples; // Debug.Log("Average for metric "+i+": "+metricAverages[i]); float sqdif = 0; foreach (float s in stdev_samples[i]) { sqdif += Mathf.Pow(s - metricAverages[i], 2f); } sqdif = sqdif / numSamples; stdev.Add(Mathf.Sqrt(sqdif)); // Debug.Log("Standard deviation for metric "+i+": "+stdev[i]); } foreach (FieldInfo field in d.generator.GetType().GetFields()) { bool useParam = true; foreach (Attribute _attr in field.GetCustomAttributes(false)) { if (_attr is TunableAttribute) { //We already know this parameter is good so don't worry. useParam = false; } } if (!useParam) { continue; } //Remember the original value object original_value = field.GetValue(b); //Change the value to something List <object> sampleValues = GetSampleValues(field, b); // Debug.Log(sampleValues.Count+" sample values found"); //For each sample value, change the field to that value, run samples, get average foreach (object o in sampleValues) { field.SetValue(b, o); List <float> sampleData = new List <float>(); for (int i = 0; i < d.metricList.Count; i++) { sampleData.Add(0); } bool sampleFailed = false; for (int _ = 0; _ < numSamples; _++) { try{ object output = d.GenerateContent(); for (int i = 0; i < d.metricList.Count; i++) { GeneratorMetric m = d.metricList[i]; sampleData[i] += (float)m.method.Invoke(null, new object[] { output }); } } catch (Exception e) { //This failed, check the next value sampleFailed = true; break; } } if (sampleFailed) { continue; } //Did this change any of the metrics more than one standard deviation from the original sampling? bool nextParam = false; for (int i = 0; i < d.metricList.Count; i++) { sampleData[i] = sampleData[i] / numSamples; if (Mathf.Abs(sampleData[i] - metricAverages[i]) > stdev[i]) { Debug.Log("Parameter " + field.Name + " may have an impact on metrics"); nextParam = true; GeneratorParameter p = new GeneratorParameter(field.Name, original_value, original_value, original_value, field, b); p.locked = true; res.Add(p); break; } } if (nextParam) { field.SetValue(b, original_value); break; } } field.SetValue(b, original_value); } return(res); }
public void Tune(DaneshWindow dan, List <GeneratorParameter> ps, List <GeneratorMetric> ms, List <float> ts) { this.c_params = ps; this.c_metrics = ms; this.c_targets = ts; float bestScore = 0f; object[] bestArray = new object[ps.Count]; //Pick a random spot float time = Time.realtimeSinceStartup; object[] ex = new object[ps.Count]; for (int s = 0; s < ps.Count; s++) { ex[s] = ps[s].GetRandomValue(); } bestScore = Evaluate(ex, 50, dan); bestArray = ex; EditorUtility.DisplayProgressBar("Automatic Tuning In Progress", "Working...", 0f); for (int iter = 0; iter < iterations; iter++) { if (bestScore > 0.98f) { break; } //Find all of the neighbouring parameter sets List <object[]> nbs = CalculateNeighbours(ex); float bestThisRound = bestScore; object[] bestArrayThisRound = new object[c_params.Count]; foreach (object[] nb in nbs) { float score = Evaluate(nb, 50, dan); if (score > bestThisRound) { bestThisRound = score; bestArrayThisRound = nb; } } if (bestThisRound > bestScore) { bestScore = bestThisRound; bestArray = bestArrayThisRound; ex = bestArrayThisRound; } else { //Random restart ex = new object[c_params.Count]; for (int s = 0; s < c_params.Count; s++) { ex[s] = ps[s].GetRandomValue(); } } EditorUtility.DisplayProgressBar("Auto-tuning", "Searching parameter space... " + (100 * (float)iter / (float)iterations).ToString("F0") + " percent complete", (float)iter / (float)iterations); } EditorUtility.ClearProgressBar(); //Apply the parameters object[] pvs = bestArray; for (int i = 0; i < pvs.Length; i++) { c_params[i].SetValue(pvs[i]); } }