Skip to content

Secure Updates

Deploying models to production systems with zero downtime particularly when those models can be updated based on streaming data poses a number of challenges. Principle among these is that these models don't get polluted with 'bad' data that could affect the results of the model.

To help mitigate this for the stochastic gradient descent models an updateSecure function is made available for the Linear Regression and Logistic Classification models once fit.

The logic used by this function is populated based on the addition of threshFunc and deleteRows to the paramDict parameter for each of the .ml.online.sgd fitting functions.

The following outlines the behaviors supported by the threshFunc parameter:

option format description
max max|(max;val) Set the maximum allowed value, by default this is the maximum value within the original fit dataset when using max, if using (max;val) then the maximum accepted value is val
min min|(min;val) Set the minimum allowed value, by default this is the minimum value within the original fit dataset when using min, if using (min;val) then the minimum accepted value is val
avg avg|(avg;dev) When using avg data must be within avg +/- 2*standard deviation, when using (avg;dev) new data must be within avg +/- dev*standard deviation

By default the optional parameter deleteRows is set to 0b, in this instance the presence of values which fall outside the bounds of threshFunc will result in an error. If set to 1b any rows that fall outside the bounds of threshFunc will be removed and the model updated with any data that does conform with requirements.

Examples:

The example below makes use of the linear regression model but the same logic and workflow also works for the logistic classification model.

Example 1: Apply updateSecure after fitting linear model

// Generate data
q)X:10 3#30?10f
q)y:10?10f
q)X2:5 3#15?10f
q)y2:5?10f

// Fit linear regression model
q)show mdl:.ml.online.sgd.linearRegression.fit[X;y;1b;enlist[`threshFunc]!enlist (min,max)]
modelInfo   | `theta`iter`diff`trend`paramDict`inputType!(-0.02693591 0.90007..
predict     | {[config;features]
  config:config`modelInfo;
  if[config`trend..
update      | {[config;secure;features;target]
  modelInfo:config`modelInfo;
..
updateSecure| {[config;secure;features;target]
  modelInfo:config`modelInfo;
..

// Apply updateSecure
q)mdl.updateSecure[X2;y2]
'Input column(s): 0 have values outside of given threshold bounds: 0.8388858 for function: min
  [3]  /Users/test/projects/ml/insights/ml-tools/ml-analytics/src/online/sgd/utils.q:530: .ml.online.sgd.util.threshCheck:
      "threshold bounds: ",bounds," for function: ",string threshFunc;
    $[not deleteRow;'printCol;-1 printCol];
                    ^
    rows:asc distinct raze online.sgd.util.findRow[threshFunc;threshBound;X]each idx;
  [2]  /Users/test/projects/ml/insights/ml-tools/ml-analytics/src/online/sgd/utils.q:503: .ml.online.sgd.util.checkX:
  if[0=count threshFunc;:(::)];
  distinct raze online.sgd.util.threshCheck[features;deleteRow]'[threshFunc;threshBound]
                                                            ^
  }

// Set default dictionary to delete rows instead of erroring
q)show mdl1:.ml.online.sgd.linearRegression.fit[X;y;1b;`threshFunc`deleteRow!(min,max;1b)]
modelInfo   | `theta`iter`diff`trend`paramDict`inputType!(-0.05745156 0.97512..
predict     | {[config;features]
  config:config`modelInfo;
  if[config`trend..
update      | {[config;secure;features;target]
  modelInfo:config`modelInfo;
..
updateSecure| {[config;secure;features;target]
  modelInfo:config`modelInfo;
..

// Apply updateSecure
q)mdl1.updateSecure[X2;y2]
Input column(s): 0,1,2 have values outside of given threshold bounds: 0.8388858 1.780839 2.306385 for function: min
Row(s) 2 3 4 removed from dataset

Input column(s): 2 have values outside of given threshold bounds: 7.111716 for function: max
Row(s) 0 3 removed from dataset

modelInfo   | `theta`iter`diff`trend`paramDict`inputType!(-0.1185931 0.920137..
predict     | {[config;features]
  config:config`modelInfo;
  if[config`trend..
update      | {[config;secure;features;target]
  modelInfo:config`modelInfo;
..
updateSecure| {[config;secure;features;target]
  modelInfo:config`modelInfo;
..

// Explicitly set upper and lower bounds of acceptable values
q)show mdl1:.ml.online.sgd.linearRegression.fit[X;y;1b;`threshFunc`deleteRow!(((min;0.1);(max;9.9));1b)]
modelInfo   | `theta`iter`diff`trend`paramDict`inputType!(-0.02812883 0.41534..
predict     | {[config;X]
  config:config`modelInfo;
  theta:config`theta;
  ..
update      | {[config;secure;X;y]
  modelInfo:config`modelInfo;
  theta:mode..
updateSecure| {[config;secure;X;y]
  modelInfo:config`modelInfo;
  theta:mode..

q)mdl1.updateSecure[X2;y2]
Input column(s): 1 have values outside of given threshold bounds: 0.8904193 for function: min
Row(s) 3 removed from dataset

modelInfo   | `theta`iter`diff`trend`paramDict`inputType!(-0.01304417 0.49747..
predict     | {[config;X]
  config:config`modelInfo;
  theta:config`theta;
  ..
update      | {[config;secure;X;y]
  modelInfo:config`modelInfo;
  theta:mode..
updateSecure| {[config;secure;X;y]
  modelInfo:config`modelInfo;
  theta:mode..