我在我的 React 应用程序中使用 ml5.js 设置,单击一个按钮来训练模型,然后单击另一个按钮进行预测。测试按钮第一次工作,但第二次抛出错误:
TypeError: Cannot read property 'classify' of undefined
我相信这是因为一旦我运行预测部分,模型就会被删除?因为分类器现在是未定义的。我该如何修改它,以便我可以反复单击测试按钮并每次都获得新的预测。
我尝试了 save() 函数,但显然它只下载模型而不为应用程序保存它。
export const Video: React.FC<ComponentProps> = (props: ComponentProps) => {
const [prediction, setPrediction] = useState<string>();
let capture: p5Types.Element;
let classifier: any;
const setup = (p5: p5Types, canvasParentRef: Element) => {
capture = p5.createCapture(p5.VIDEO).parent(canvasParentRef);
const featureExtractor = ml5.featureExtractor('MobileNet', modelReady);
classifier = featureExtractor.classification(capture, videoReady);
}
const draw = (p5: p5Types) => {
}
function gotResult() {
classifier.classify(capture, (err: any, result: any) => {
setPrediction(result[0].label);
});
}
function train() {
classifier.train((lossValue: any) => {
console.log('Loss is', lossValue);
});
//classifier.save();
}
return (<div><Sketch setup={setup} draw={draw} className="sketch" />
<div className="button">
<Button variant="contained" color="primary" onClick={() => classifier.addImage('first')}>First</Button>
<Button variant="contained" color="primary" onClick={() => classifier.addImage('second')}>Second</Button>
</div>
<div className="secondbutton">
<Button variant="contained" color="primary" onClick={() => train()}>Train!</Button>
<Button variant="contained" color="primary" onClick={() => gotResult()}>Test!</Button>
<br />
<span>Prediction: {prediction}</span>
</div>
</div>)
;
};
代码沙盒:
https://codesandbox.io/s/hardcore-solomon-zb34l?file=/src/Component.tsx
更新代码:
export const VideoComponent: React.FC<ComponentProps> = (props: ComponentProps) => {
const [prediction, setPrediction] = useState<string>();
const [confidence, setConfidence] = useState<string>();
const [trainingComplete, setTrainingComplete] = useState<boolean>();
const captureRef = useRef<p5Types.Element>();
const classifierRef = useRef<any>();
const setup = (p5: p5Types, canvasParentRef: Element) => {
const capture = p5.createCapture(p5.VIDEO).parent(canvasParentRef);
const featureExtractor = ml5.featureExtractor("MobileNet", modelReady);
captureRef.current = capture;
classifierRef.current = featureExtractor.classification(capture, videoReady);
}
const draw = (p5: p5Types) => {
}
function gotResult() {
console.log('classifier in results', classifierRef.current);
classifierRef.current.classify(captureRef.current, (err: any, result: any) => {
setPrediction(result[0].label);
setConfidence(result[0].confidence);
});
}
function train() {
console.log('classifier in train', classifierRef.current);
classifierRef.current?.classify.train((lossValue: any) => {
console.log('Loss is', lossValue);
if (lossValue == null) {
//setTrainingComplete(true);
console.log('training complete')
}
});
}
return (
<div>
<Sketch setup={setup} draw={draw} className="sketch" />
<div className="button">
<Button variant="contained" color="primary" onClick={() => { classifierRef.current?.classifier.addImage('first'); console.log('image added') }}>First</Button>
<Button variant="contained" color="primary" onClick={() => { classifierRef.current?.classifier.addImage('second'); console.log('image added') }}>Second</Button>
</div>
<div className="secondbutton">
<Button variant="contained" color="primary" onClick={() => train()}>Train!</Button>
<Button variant="contained" color="primary" onClick={() => gotResult()}>Test!</Button>
<br />
{trainingComplete && (<span>Training Complete!</span>)}<br />
<span>Prediction: {prediction}</span><br />
</div>
</div>)
;
};