After training one model on a set of data, I'd like to get a copy of it and train each copy on different data sets. Is there a way to clone a model in such a way that after the cloning each of them can be trained separately?
I've already tried to save the model in my localstorage and generate a copy from there but tensorflow complains that some variable names are already in use.
In case someone else is interested, I have eventually solved it getting all the weights of the model I wanted to copy with the getweights() function, creating a new model with the same architecture and then copying back the other model's weight to it with setweights()
Step 1. You extract the model with tf.io.withSaveHandler via save(), it's callback style so you may want to wrap it with a Promise for modern codebases.
const modelArtifacts = await new Promise<tf.io.ModelArtifacts>(resolve => {
model.save(
tf.io.withSaveHandler(artifacts => {
resolve(model);
// Optional, prevents type error.
return Promise.resolve({
modelArtifactsInfo: {
dateSaved: new Date(),
modelTopologyType: "JSON"
}
});
})
);
});
Step 2. You load the extracted contents into a new model with tf.io.fromMemory.
const newModel = await tf.loadLayersModel(tf.io.fromMemory(modelArtifacts));
Related
I have an external API POSTing data to my project. I want to move my project to Strapi. But ofcourse, the shape of that external POST does not match the data creation endpoint of my Strapi model. Also it's in XML so I need to parse it fist and need to mutate the incoming data to match the model better. How should one go about.
My thoughts include:
create middleware that checks for the incoming data and remodels it to match my model
create a route that points to a controller that handles the data and creates the model from code. This I have trouble in finding howto in the docs, but I guess it would be: strapi.query('myModel').create({})
I would love to hear some ideas and concepts from people familiar with Strapi.
So for the answer to this question.
You will have to use this concept - https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers
Customizing your create controller function.
And at the beginning of the function, you will have to check the format of ctx.request.body.
If the content has an XML format, in this case, you will have to convert it in JSON.
Path — api/**/controllers/**.js
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
module.exports = {
/**
* Create a record.
*
* #return {Object}
*/
async create(ctx) {
// if ctx.request.body is XML
// ctx.request.body = convertXMLtoJSON(ctx.request.body);
// you will have to find a code that convert XML to JSON
// and simply add id in this function
let entity;
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
entity = await strapi.services.restaurant.create(data, { files });
} else {
entity = await strapi.services.restaurant.create(ctx.request.body);
}
return sanitizeEntity(entity, { model: strapi.models.restaurant });
},
};
I'm creating a model that I will use to authenticate users for API access, and I have a secret field where I want to store a Base64 encoded uuid/v4 generated value.
I went through the different field types and options, but still not seeing how I could achieve this.
Is there a way to hook in model instance creation, and set the value of my secret field ?
Yes, you can use the pre hooks.
In your situation, the basics would be:
AuthenticationModel.schema.pre("save", function(next) {
const secretValue = generateSecretValue();
this.secret = secretValue;
next();
});
That would go before your final AuthenticationModel.register(); in your model.js file.
This is how I set it up, also with the pre-save hook. My problem before was that I was getting the same random number again until I restarted the server.
Store.schema.pre('save', function (next) {
if (!this.updateId && this.isNew) {
// generates a random ID when the item is created
this.updateId = Math.random().toString(36).slice(-8);
}
next();
});
Using this.isNew was also useful in my case.
I have a small blog app that has Articles and Tags. Nothing fancy so far. Every Article can have many Tags.
The Laravel backend delivers the data via API calls from Axios in the Vue Frontend. In the Laravel models Article has a method
public function tags(){
return $this->belongsToMany('App\Tag');
}
and vice versa for tags. I have a pivot table and all this follow pretty much the example given in https://laracasts.com/series/laravel-5-fundamentals/episodes/21
All this works fine.
Now let´s say I want to call in Vue the method deleteTag() which should remove the connection between Article and Tag. Things are behind the scenes a bit more complicated as "addTag" in PHP also adds a new Tag Model AND the connection between Tag and Article in the Pivot table OR connects - if the Tag exists already - an existing Tag with Article.
What is the best way to achieve this?
What I´m doing so far:
ArticleTags.vue
deleteTag(tagName){
let articleId = this.articleId;
this.$store.dispatch('removeTagFromArticle', { articleId, tagName });
},
index.js (Vuex store)
actions: {
removeTagFromArticle(context,param) {
axios.post('api/articles/delete-tag/', param)
.then((res) => {
let article = context.getters.getArticleById(param.articleId);
let tagName = param.tagName;
context.commit('deleteTag', {article, tagName} );
})
.catch((err) => console.error(err));
} }
mutations : { deleteTag (state, { article, tag }) {
let tagIndex = article.tags.indexOf(tag);
article.tags.splice(tagIndex,1);
} }
ArticleController.php
/**
* Remove Tag from Article
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function deleteTag(Request $request)
{
$tag = \App\Tag::firstOrCreate(array('name' => $request->tagName));
$article = Article::findOrFail($request->articleId);
$result = $article->tags()->detach([$tag->id]);
$this->cleanUpTags();
return response('true', 200);
}
routes/web.php
Route::post('api/articles/delete-tag', 'ArticleController#deleteTag');
This works so far. The code does exactly what it should. Only it feels really clumsy. And probably to complicated. Maybe it´s because the example is simple but the whole setup is big.
Nonetheless I´m trying to improve my coding. :)
So my questions are:
1) Would it be better to pass the article object in Vue to the store instead of the articleId?
2) Is the idea of using Array.slice() in the store too complicated? This could be done straight in the components.
3) Does it make sense to reload the whole store from Laravel after deleting the tag PHP-wise?
Edit: in case someone is looking for this question and how I solved it at the end. The source code for this app can be found at https://github.com/shopfreelancer/streamyourconsciousness-laravel
Personally I like to use ID's to reference any database resource aswell as keeping my objects in javascript somewhat the same as my API.
1
In this case I would have changed my tags to objects instead of strings and send an ID of the tag to my API.
An example of my article would look like:
let article = {
tags: [{ id: 1, name: 'tag 1' }, { id: 2 ... }]
}
Using objects or IDs as parameters are in my opinion both fine. I should stick with objects if you like "cleaner" code, there will only be one place to check if the ID is present in your object aswell as the selection of the ID.
Case:
// Somehwere in code
this.deleteArticle(article);
// Somehwere else in code
this.deleteArticle(article);
// Somewhere else in code
this.deleteArticle(article);
// Function
deleteArticle(article) {
// This check or other code will only be here instead of 3 times in code
if (!article.hasOwnProperty('id')) {
console.error('No id!');
}
let id = article.id;
...
}
2
Normally I would keep the logic of changing variables in the components where they are first initialized. So where you first tell this.article = someApiData;. Have a function in there that handles the final removal of the deleted tag.
3
If you are looking for ultimate world domination performance I would remove the tag in javascript. You could also just send the updated list of tags back in the response and update all tags of the article with this data and keep your code slim. However I still like to slice() the deleted tag from the array.
Remember this is my opinion. Your choises are completely fine and you should, like I do myself, never stop questioning yours and others code.
I want to pass a property of my model to the template, so I presume I need a serializeData function, I tried this
serializeData:function(){
return this.model.toJSON().extend({_schema:this.model.schema});
}
but it complained about not being able to extend the output of toJSON. This must be a standard trick, stick some value from the prototype into the serialised form so the template can get it's hands on it.
Use templateHelpers for this use case – serializeData works better for replacing the model attributes entirely, or scoping them down.
templateHelpers: function()
{
return { _schema: this.model.schema };
}
Harladson's answers is the best, but in case someone else comes looking different approach you can do this:
serializeData:function(){
var data = this.model.toJSON();
data._schema = this.model.schema;
return data;
}
I am using Parse for my backend and want to search for existing friend requests and update those instead of creating new ones (if there is already an existing one).
I thought I figured out how to do it but when I submit new friend requests they get created as new objects instead of updating the old one, even though I found an existing request.
Here is the code I am using:
Parse.Cloud.beforeSave("FriendRequest", function(request, response) {
//search for an existing friend request with the same "from" and "to"
var query = new Parse.Query("FriendRequest");
query.equalTo("from", request.object.get("from"))
.equalTo("to", request.object.get("to"));
query.find({
success: function(results) {
if(results.length > 0)
{
var result = results[0];
//the new request id is undefined as expected
console.log("request id: " + request.object.id);
//the result id is valid for an object in the db as expected
console.log("result id: " + results[0].id);
//set the id of the request to the id of the existing db object
request.object.id = results[0].id;
//the valid id is now in the request object id
console.log("request id: " + request.object.id);
//after response.success, the database shows a new entry
//with a different id
//instead of updating the existing entry
response.success();
}
}
});
});
There isn't a lot going on here. The query does come back successful with the correct entry in the database. I can confirm that I get the correct objectId for the existing item in the database. Any thoughts or ideas are appreciated!
You can't manually set the objectId of an object.
If you want beforeSave to NOT create a new object (which is what you're about to do when beforeSave is called), you need to manually update the existing object and then respond with a failure. If you respond with response.success(), the object will be saved normally.
In your code, you don't seem to make any changes to the existing object. All you really need to do is to return response.error (https://parse.com/docs/cloud_code_guide#functions-onsave)
Of course, you should also handle this in your code somehow. Either by alerting the user, or handling it silently.
However; why does your code attempt to save a new friend request if one already exist? Your app should know that one exists and disable the friend request button or whatever the UI offers.