如何在 sagas 中使用异步加载的资产和 react native?
How to use async loaded assets in sagas with react native?
我正在使用 redux-saga 和 tensorflow js 构建一个 Expo 应用程序。初始化应用程序时必须异步加载模型。在所有示例中,模型都加载到组件中并存储在组件的状态中。
但是我想在 saga 中而不是直接在组件中执行推理。
我不知道如何编写初始化过程以便能够从 saga 中访问加载的模型。
在 App.js
我有以下内容:
export default class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
)
} else {
return (
<Provider store={store}>
.....
</Provider>
)
}
并且我已将 tfjs doc 模型的初始化和预热代码放入 this._loadResourcesAsync
:
_loadResourcesAsync = async () => {
await Promise.all([
Asset.loadAsync([
require('./assets/images/splash.png'),
require('./assets/images/icon.png'),
]),
Font.loadAsync({
...Icon.MaterialIcons.font,
...Icon.MaterialCommunityIcons.font,
...Icon.FontAwesome.font,
...Icon.Feather.font,
}),
tf.ready(),
])
const modelUrl = 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
const model = await tf.loadGraphModel(modelUrl);
const zeros = tf.zeros([1, 224, 224, 3]);
model.predict(zeros).print();
};
我不知道以后如何在 saga 中访问这个模型。
编辑
@senthil 建议使用单例模式后,我尝试将此代码放在单独的文件中或直接放在 _loadResourcesAsync
中,但这会使应用程序崩溃
const modelUrl = 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
let instance;
async function createInstance() {
console.log("createInstance")
const model = await tf.loadGraphModel(modelUrl);
console.log("model", model)
// Warm-up
const zeros = tf.zeros([1, 224, 224, 3]);
console.log("zeros", zeros)
model.predict(zeros).print();
return {model}
}
async function getInstance() {
console.log("getInstance")
console.log("instance", instance)
if (!instance) {
instance = await createInstance();
}
return instance;
}
const {model} = await getInstance()
console.log("encoder", model)
在日志中我看到代码卡在 const model = await tf.loadGraphModel(modelUrl);
在这种情况下,您必须保持状态,例如
// let's assume, this is your App.js
import MLModel from "./MLModel";
export default class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete) {
return (
<AppLoading
startAsync={async () => {
await this._loadOtherResources();
MLModel.loadModel(() => {
this.setState({isLoadingComplete:true});
})
}}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
)
} else {
return (
<Provider store={store}>
.....
</Provider>
)
}
在你的 MLModel.js
// MlModel.js file should have a class
class MLModel {
let model = null;
getModel(){
return this.model;
}
async loadModel(onModelLoadCompleteCallback) {
const modelUrl = '<URL>';
const model = await tf.loadGraphModel(modelUrl);
// I'm not sure what'll below line do exactly like mutate or return
// I'm assuming this is async and will mutate the model object.
await model.predict(zeros).print();
this.model = model;
onModelLoadCompleteCallback();
}
}
export default new MLMoldel();
以同样的方式,您也应该能够从其他任何地方加载模型。
注意:我没有执行和检查,可能有一些编译错误忽略它们,但最终这是我想传达的东西。
我正在使用 redux-saga 和 tensorflow js 构建一个 Expo 应用程序。初始化应用程序时必须异步加载模型。在所有示例中,模型都加载到组件中并存储在组件的状态中。
但是我想在 saga 中而不是直接在组件中执行推理。
我不知道如何编写初始化过程以便能够从 saga 中访问加载的模型。
在 App.js
我有以下内容:
export default class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
)
} else {
return (
<Provider store={store}>
.....
</Provider>
)
}
并且我已将 tfjs doc 模型的初始化和预热代码放入 this._loadResourcesAsync
:
_loadResourcesAsync = async () => {
await Promise.all([
Asset.loadAsync([
require('./assets/images/splash.png'),
require('./assets/images/icon.png'),
]),
Font.loadAsync({
...Icon.MaterialIcons.font,
...Icon.MaterialCommunityIcons.font,
...Icon.FontAwesome.font,
...Icon.Feather.font,
}),
tf.ready(),
])
const modelUrl = 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
const model = await tf.loadGraphModel(modelUrl);
const zeros = tf.zeros([1, 224, 224, 3]);
model.predict(zeros).print();
};
我不知道以后如何在 saga 中访问这个模型。
编辑
@senthil 建议使用单例模式后,我尝试将此代码放在单独的文件中或直接放在 _loadResourcesAsync
中,但这会使应用程序崩溃
const modelUrl = 'https://storage.googleapis.com/tfjs-models/savedmodel/mobilenet_v2_1.0_224/model.json';
let instance;
async function createInstance() {
console.log("createInstance")
const model = await tf.loadGraphModel(modelUrl);
console.log("model", model)
// Warm-up
const zeros = tf.zeros([1, 224, 224, 3]);
console.log("zeros", zeros)
model.predict(zeros).print();
return {model}
}
async function getInstance() {
console.log("getInstance")
console.log("instance", instance)
if (!instance) {
instance = await createInstance();
}
return instance;
}
const {model} = await getInstance()
console.log("encoder", model)
在日志中我看到代码卡在 const model = await tf.loadGraphModel(modelUrl);
在这种情况下,您必须保持状态,例如
// let's assume, this is your App.js
import MLModel from "./MLModel";
export default class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete) {
return (
<AppLoading
startAsync={async () => {
await this._loadOtherResources();
MLModel.loadModel(() => {
this.setState({isLoadingComplete:true});
})
}}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
)
} else {
return (
<Provider store={store}>
.....
</Provider>
)
}
在你的 MLModel.js
// MlModel.js file should have a class
class MLModel {
let model = null;
getModel(){
return this.model;
}
async loadModel(onModelLoadCompleteCallback) {
const modelUrl = '<URL>';
const model = await tf.loadGraphModel(modelUrl);
// I'm not sure what'll below line do exactly like mutate or return
// I'm assuming this is async and will mutate the model object.
await model.predict(zeros).print();
this.model = model;
onModelLoadCompleteCallback();
}
}
export default new MLMoldel();
以同样的方式,您也应该能够从其他任何地方加载模型。
注意:我没有执行和检查,可能有一些编译错误忽略它们,但最终这是我想传达的东西。