File size: 2,943 Bytes
dee7f43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.io.File;
import java.util.Arrays;
import java.util.Map;
import org.fireviewer.litert.training.OnDeviceLearning;

/** Real Android CPU exercise: two image sizes, train, durable save and optimizer resume. */
public final class FireDetectorRuntimeCheck {
  public static void main(String[] args) {
    File model=new File(args[0]), root=new File(args[1]);
    int threads=args.length>2?Integer.parseInt(args[2]):2;
    String schema="0000000000000000000000000000000000000000000000000000000000000000";
    Map<String,Object> square=TrainingRuntimeCheck.inputs("x",TrainingRuntimeCheck.image(128,128));
    Map<String,Object> rectangle=TrainingRuntimeCheck.inputs("x",TrainingRuntimeCheck.image(128,192));
    float[] target=new float[600];
    target[0]=.3f;target[1]=.3f;target[2]=.7f;target[3]=.7f;target[4]=0;target[5]=1;
    File checkpoint;float[] trained,continued;float firstLoss,secondLoss;
    System.out.println("FIRE_CHECK opening "+model.getName());
    try(OnDeviceLearning session=new OnDeviceLearning(model,schema,threads)) {
      System.out.println("FIRE_CHECK opened");
      float[] original=session.infer(square).get("detections").getValues();
      System.out.println("FIRE_CHECK infer "+original.length);
      firstLoss=session.train(square,target,.001f);
      trained=session.infer(square).get("detections").getValues();
      TrainingRuntimeCheck.check(!Arrays.equals(original,trained),"Training did not change outputs");
      checkpoint=session.save(root,"synthetic-android-runtime-fixture",1L);
      System.out.println("FIRE_CHECK saved loss="+firstLoss);
      secondLoss=session.train(rectangle,target,.001f);
      continued=session.infer(rectangle).get("detections").getValues();
      System.out.println("FIRE_CHECK continued loss="+secondLoss);
    }
    try(OnDeviceLearning resumed=new OnDeviceLearning(model,schema,threads)) {
      resumed.restore(checkpoint);
      TrainingRuntimeCheck.check(Arrays.equals(trained,resumed.infer(square).get("detections").getValues()),"Restored predictions differ");
      resumed.train(rectangle,target,.001f);
      TrainingRuntimeCheck.check(Arrays.equals(continued,resumed.infer(rectangle).get("detections").getValues()),"Resumed optimizer differs");
    }
    try(OnDeviceLearning invalid=new OnDeviceLearning(model,"1000000000000000000000000000000000000000000000000000000000000000",threads)) {
      boolean rejected=false;
      try { invalid.restore(checkpoint); } catch(IllegalArgumentException expected) { rejected=true; }
      TrainingRuntimeCheck.check(rejected,"Incompatible class schema accepted");
    }
    System.out.println("ANDROID_FIRE_TRAINING_PASS {\"runtime\":\""+org.tensorflow.lite.TensorFlowLite.runtimeVersion()+"\",\"mixed_shapes\":[[128,128],[128,192]],\"train\":true,\"restore_exact\":true,\"optimizer_resume_exact\":true,\"incompatible_schema_rejected\":true,\"first_loss\":"+firstLoss+",\"second_loss\":"+secondLoss+"}");
  }
}