TL;DR
In Quartz 1, you may use this cron: 59 59 23 31 12 ? 2099
(last valid date).
In Quartz 2, you may use this cron: 0 0 0 1 1 ? 2200
Using an expression far in the future
Made some quick tests using org.quartz.CronExpression
.
String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
System.out.println(valid);
if (valid) {
CronExpression cronExpression = new CronExpression(exp);
System.out.println(cronExpression.getNextValidTimeAfter(new Date()));
}
When I do String exp = "# 0 0 0 1 1 ?";
, the isValid
test returns false
.
With the sample given above yet, the output is the following:
true
null
Meaning:
- the expression is valid;
- there is no upcoming date which matches this expression.
For the scheduler to accept a cron trigger, though, the latter must match a date in the future.
I tried several years and figured out that once the year is above 2300, Quartz seems not to bother anymore (though I did not find a mention to a maximal value for the year in Quartz 2's documentation). There might be a cleaner way to do this, but this will satisfy my needs for now.
So, in the end, the cron I propose is 0 0 0 1 1 ? 2200
.
Quartz 1 variant
Note that, in Quartz 1, 2099 is the last valid year. You can therefore adapt your cron expression to use Maciej Matys's suggestion: 59 59 23 31 12 ? 2099
Alternative: Using a date in the past
Arnaud Denoyelle suggested something more elegant, which my test above validates as a correct expression: instead of choosing a date in a far future, choose it in a far past:
0 0 0 1 1 ? 1970
(the first valid expression according to Quartz documentation).
This solution does not work though.
hippofluff highlighted that Quartz will detect an expression in past will never be executed again and therefore throw an exception.
org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.
This seems to have been in Quartz for a long time.
Lessons learned: the test is not foolproof as is
This highlights a weakness of my test: in case you want to test a CronExpression
, remember it has to have a nextValidTime
1. Otherwise, the scheduler you will pass it to will simply reject it with the above mentioned exception.
I would advise adapting the test code as follows:
String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
if (valid) {
CronExpression cronExpression = new CronExpression(exp);
valid = cronExpression.getNextValidTimeAfter(new Date()) != null;
}
System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail."));
There you go: no need to think, just read the output.
1 This is the part I forgot when testing Arnaud's solution making me the fool and proving my test wasn't me-proof.
This worked for me !!
Use PyDrive API
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
# 1. Authenticate and create the PyDrive client.
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
# 2. Save Keras Model or weights on google drive
# create on Colab directory
model.save('model.h5')
model_file = drive.CreateFile({'title' : 'model.h5'})
model_file.SetContentFile('model.h5')
model_file.Upload()
# download to google drive
drive.CreateFile({'id': model_file.get('id')})
Same for weights
model.save_weights('model_weights.h5')
weights_file = drive.CreateFile({'title' : 'model_weights.h5'})
weights_file.SetContentFile('model_weights.h5')
weights_file.Upload()
drive.CreateFile({'id': weights_file.get('id')})
Now, check your google drive.
On next run, try reloading the weights
# 3. reload weights from google drive into the model
# use (get shareable link) to get file id
last_weight_file = drive.CreateFile({'id': '1sj...'})
last_weight_file.GetContentFile('last_weights.mat')
model.load_weights('last_weights.mat')
A Better NEW way to do it (post update) ... forget the previous (also works)
# Load the Drive helper and mount
from google.colab import drive
drive.mount('/content/drive')
You will be prompted for authorization
Go to this URL in a browser: something like :
accounts.google.com/o/oauth2/auth?client_id=.....
obtain the auth code from the link, paste your authorization code in the space
Then you can use drive normally as your own disk
Save weights or even the full model directly
model.save_weights('my_model_weights.h5')
model.save('my_model.h5')
Even a Better way, use call backs, which automatically checks if the model at each epoch achieved better than the best saved one and save the one with best validation loss so far.
my_callbacks = [
EarlyStopping(patience=4, verbose=1),
ReduceLROnPlateau(factor=0.1, patience=3, min_lr=0.00001, verbose=1),
ModelCheckpoint(filepath = filePath + 'my_model.h5',
verbose=1, save_best_only=True, save_weights_only=False)
]
And use the call back in the model.fit
model.fit_generator(generator = train_generator,
epochs = 10,
verbose = 1,
validation_data = vald_generator,
callbacks = my_callbacks)
You can load it later, even with a previous user defined loss function
from keras.models import load_model
model = load_model(filePath + 'my_model.h5',
custom_objects={'loss':balanced_cross_entropy(0.20)})
Best Answer
Example code for Dynamic Quartz JOB Scheduling:
Maven Dependencies
Application Context File (dynamic-jobs.xml)
Java Class for Task
Java Class to Create Dynamic Job