Vue and Tensorflow: Save classifier examples to localstorage - javascript

I'm using #tensorflow-models/knn-classifier to classify my models and #tensorflow-models/mobilenet to study new models.
methods: {
async init() {
// load the load mobilenet and create a KnnClassifier
this.classifier = knnClassifier.create();
this.mobilenet = await mobilenetModule.load();
},
async addExample() {
let selected = document.getElementById("options");
this.class = selected.options[selected.selectedIndex].value;
const img = tf.browser.fromPixels(this.$children[0].webcam.webcamElement);
const logits = this.mobilenet.infer(img, "conv_preds");
this.classifier.addExample(logits, parseInt(this.class));
}
How can I save to localStorage my examples, which I added to the classifier and then load them in init() method? Because currently, I'm losing all my models after the page refresh.
Sorry maybe for the wrong terminology, I'm so new in Tensorflow js.

So, after small research I managed to save and load data with the next methods:
async toDatasetObject(dataset) {
const result = await Promise.all(
Object.entries(dataset).map(async ([classId, value]) => {
const data = await value.data();
return {
label: Number(classId),
data: Array.from(data),
shape: value.shape
};
})
);
return result;
},
fromDatasetObject(datasetObject) {
return Object.entries(datasetObject).reduce(
(result, [indexString, { data, shape }]) => {
const tensor = tf.tensor2d(data, shape);
const index = Number(indexString);
result[index] = tensor;
return result;
},
{}
);
},
And then I just load it:
this.classifier.setClassifierDataset(
this.fromDatasetObject(JSON.parse(localStorage.getItem("my-data")))
);

Related

Reactjs problem rendering binary image retrieved from mongodb

Hello so I have images in a mongodb database and I'm trying to render them on the client side however It's not working. I convert the buffer unit8 data into base64 so I can render it it seemd to work and been stored in the images state but images are not accessible by associative array.
useEffect( () => {
const getAllDoctors = async () => {
const result = await api.get('doctor/all')
const myImages = []
setDoctors(result.data)
await result.data.forEach(async doctor => {
myImages[doctor._id] = await base64_arraybuffer(doctor.photo.data.data)
})
setImages(myImages)
setLoading(false)
}
getAllDoctors()
}, [])
as for the render
return (
<div>
{
images.map((image, key) => {
console.log(doctors)
return (
<div key={key}>
<img alt={'image'} src={`data:image/png; base64, ${image}`}/>
<div>{`Doctor + ${images}`}</div>
</div>
)
})
}
</div>
);
converter (not mine):
const base64_arraybuffer = async (data) => {
const base64url = await new Promise((r) => {
const reader = new FileReader()
reader.onload = () => r(reader.result)
reader.readAsDataURL(new Blob([data]))
})
return base64url.split(",", 2)[1]
}
Two things
The way your array assignment is doesn't make sense. If _id is a ID string, then you are using a string to key an array, the data assigned at that key won't be included in loops. Use Array.prototype.push to add the item to the next available index.
Array.prototype.forEach and async / await don't play nice together due to the nature of callbacks. Try using a traditional loop.
useEffect(() => {
const getAllDoctors = async () => {
const result = await api.get("doctor/all");
const myImages = [];
setDoctors(result.data);
for (const doctor of result.data) {
const image = await base64_arraybuffer(doctor.photo.data.data);
myImages.push(image)
}
setImages(myImages);
setLoading(false);
};
getAllDoctors();
}, []);

Using return data from an async function, in another function

I'm doing a little data analysis from chess.com data
I have this code
const getUsernames = async function() {
let response = await chessAPI.getCountryPlayers('RE')
names = [...response.body.players]
//console.log(names)
return names
}
const grabPlayerScores = async function() {
let players = getUsernames()
// let playerStats = [];
for (i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(i)
console.log(data)
}
}
grabPlayerScores();
I can't get the other function to await the return of the first. I know I should use promises or structure my other function differently but I'm still getting the hang of these types of functions.
As a best practice, you should make sure all of your functions return a value. Use const for variables that will not change, and let for variables that you absolutely will change. Watch out for name = ... where you didn't write const or let, as this makes names into a global -
const getUsernames = async function() {
const response = await chessAPI.getCountryPlayers('RE')
return response.body.players // <- probably no need to copy
}
const grabPlayerScores = async function() {
const players = await getUsernames()
return Promise.all(players.map(p => chessAPI.getPlayerStats(p)))
}
Now grabPlayerScores will be a promise containing an array of all player scores -
grabPlayerScores().then(console.log).catch(console.error)
[ ..., ... ,... ]
Maybe you want the player data combined with the score data in the final output?
const grabPlayerScores = async function() {
const players = await getUsernames()
return Promise.all(players.map(async p => ({
player: p,
scores: await chessAPI.getPlayerStats(p)
})))
}
grabPlayerScores().then(console.log).catch(console.error)
[ { player: "alice", scores: ... },
{ player: "brenda", scores: ... },
{ player: "catherine", scores: ... } ]
Another good practice is to make your functions take parameters. This makes them more reusable in other areas of your program -
const getUsernames = async function(countryCode) {
const response = await chessAPI.getCountryPlayers(countryCode)
return response.body.players
}
const grabPlayerScores = async function(countryCode) {
const players = await getUsernames(countryCode)
return Promise.all(players.map(async p => ({
player: p,
scores: await chessAPI.getPlayerStats(p)
})))
}
Now you pass "RE" as an argument to your function, allowing you to easily reuse this function for other countries -
grabPlayerScores("RE").then(console.log).catch(console.error)
You need to add another await in your grabPlayerScores function to wait for getUsernames to finish.
const grabPlayerScores = async function() {
// Add an 'await' here
let players = await getUsernames();
for(let i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(i)
console.log(data)
}
}
I changed bit in your code,
const grabPlayerScores = async function () {
let players = await getUsernames();
for (i = 0; i = players.length; i++) {
let data = await chessAPI.getPlayerStats(players[i]);
console.log(data)
}
}

How do I get user details in Firebase Storage?

I'm a new programmer and very new to firebase and I'm trying to get the current user files info to display on the screen, it seems that my problem is that I can get the URL and the metadata separately, how do I combine them? how can I take everything at once?
I need to show the file name, date, time, link to download.
const getUserFiles = async () => {
if (!userUID) {
return null;
}
let listRef = storageRef.child(userUID);
listRef.listAll().then(res => {
// res.prefixes.forEach((item) => {
// });
res.items.forEach(item => {
item.getMetadata().then(item => {
var file = {
name: item.name.toString(),
timeCreated: item.timeCreated.toString(),
link: '',
};
myFiles.push(file);
});
});
res.items.forEach(item => {
let counter = 0;
item.getDownloadURL().then(url => {
myFiles[counter].link = url.toString();
});
});
});
console.log(myFiles);
};
the current method don't work! and notice that the userUID its only the uid without the user (local state)
Thanks!
The problem is with the asynchronous calls. You're making an async call in forEach and forEach expects a synchronous function.
You can change the logic to use for-of instead.
See below:
const getUserFiles = async () => {
if (!userUID) {
return null;
}
let listRef = storageRef.child(userUID);
const res = await listRef.listAll();
for (const itemRef of res.items) {
const itemMetadata = await itemRef.getMetadata();
const url = await itemRef.getDownloadUrl();
var file = {
name: itemMetadata.name.toString(),
timeCreated: itemMetadata.timeCreated.toString(),
link: url,
};
myFiles.push(file);
}
console.log(myFiles);
}

(Vuejs, Vuetify) How to avoid, loading objects twice form an API?

Im kind of an Beginner within Vuejs. Im Creating a Site which shows content that is loaded from the Backend into the Frontend. Therfore, I use Axios to connect to the API with this code:
contentList: [],
};
const mutations = {
setContent (state) {
axios
.get("http://backendapi/content")
.then(res => {
const data = res.data;
for (let key in data) {
const object = data[key];
state.contentList.push(object)
}
});
}
};
const actions = {
initContent: ({commit}) =>{
commit('setContent');
}
};
and on my Page i load the Contentlist when mounted:
mounted() {
this.$store.dispatch('initContent');
this.content = this.$store.getters.contentList
}
But the Problem is, every Time i go to another Page and back to this Page, the Content is loaded again into the contentList and everithing ist doubled.
Can someone explain, how to write this in "good Code" and avoiding loading everything double?
Thank you
You can check if already have the content on your list before making the request.
setContent (state) {
if (state.contentList.length == 0){
axios
.get("http://backendapi/content")
.then(res => {
const data = res.data;
for (let key in data) {
const object = data[key];
state.contentList.push(object)
}
});
}
}
or if you want to update each time just make sure the variable is reset each time.
axios
.get("http://backendapi/content")
.then(res => {
const data = res.data;
let contentList = [];
for (let key in data) {
const object = data[key];
contentList.push(object);
}
state.contentList = contentList;
});
Just check whether the content is already loaded before doing an axis call. Also the action is meant to execute the axios call:
const mutations = {
setContent (state, data) {
state.contentList = data
}
};
const actions = {
async initContent: ({commit, state}) =>{
if (state.contentList.length === 0) {
try {
let result = []
let response = await axios.get("http://backendapi/content")
for (let key in response.data) {
result.push(response.data[key])
}
commit('setContent', result);
} catch (error) {
// something went wrong
}
}
}
};

Handling multiple ajax requests, only do the last request

I'm doing a project that fetch different types of data from SWAPI API (people, planets, etc.) using react but I have an issue with multiple Ajax request.
The problem is when I quickly request from 2 different URL for example, 'species' and 'people', and my last request is 'species' but the load time of 'people' is longer, I will get 'people' instead.
What I want is to get the data of the last clicked request, if that make sense.
How do I achieve that? All the solution I found from Google is using jQuery.
Here's a slice of my code in src/app.js (root element) :
constructor(){
super();
this.state = {
searchfield: '',
data: [],
active: 'people'
}
}
componentDidMount() {
this.getData();
}
componentDidUpdate(prevProps, prevState) {
if(this.state.active !== prevState.active) {
this.getData();
}
}
getData = async function() {
console.log(this.state.active);
this.setState({ data: [] });
let resp = await fetch(`https://swapi.co/api/${this.state.active}/`);
let data = await resp.json();
let results = data.results;
if(data.next !== null) {
do {
let nextResp = await fetch(data.next);
data = await nextResp.json();
let nextResults = data.results
results.push(nextResults);
results = results.reduce(function (a, b) { return a.concat(b) }, []);
} while (data.next);
}
this.setState({ data: results});
}
categoryChange = (e) => {
this.setState({ active: e.target.getAttribute('data-category') });
}
render() {
return (
<Header searchChange={this.searchChange} categoryChange={this.categoryChange}/>
);
}
I made a gif of the problem here.
Sorry for the bad formatting, I'm writing this on my phone.
You have to store your requests somewhere and to abandon old ones by making only one request active. Something like:
getData = async function() {
console.log(this.state.active);
this.setState({ data: [] });
// my code starts here
if (this.controller) { controller.abort() }
this.controller = new AbortController();
var signal = controller.signal;
let resp = await fetch(`https://swapi.co/api/${this.state.active}/`, { signal });
let data = await resp.json();
let results = data.results;
if(data.next !== null) {
do {
let nextResp = await fetch(data.next);
data = await nextResp.json();
let nextResults = data.results
results.push(nextResults);
results = results.reduce(function (a, b) { return a.concat(b) }, []);
} while (data.next);
}
this.setState({ data: results});
}

Categories

Resources