def _assemble_multi_class_output(self): support_vectors = self.model.support_vectors_ coef = self.model.dual_coef_ intercept = self.model.intercept_ n_support = self.model.n_support_ n_support_len = len(n_support) kernel_exprs = self._apply_kernel(support_vectors, to_reuse=True) support_ranges = [] for i in range(n_support_len): range_start = sum(n_support[:i]) range_end = range_start + n_support[i] support_ranges.append((range_start, range_end)) # One-vs-one decisions. decisions = [] for i in range(n_support_len): for j in range(i + 1, n_support_len): kernel_weight_mul_ops = [ utils.mul(kernel_exprs[k], ast.NumVal(coef[i][k])) for k in range(*support_ranges[j]) ] kernel_weight_mul_ops.extend([ utils.mul(kernel_exprs[k], ast.NumVal(coef[j - 1][k])) for k in range(*support_ranges[i]) ]) decision = utils.apply_op_to_expressions( ast.BinNumOpType.ADD, ast.NumVal(intercept[len(decisions)]), *kernel_weight_mul_ops) decisions.append(decision) return ast.VectorVal(decisions)
def _linear_to_ast(coef, intercept): feature_weight_mul_ops = [ utils.mul(ast.FeatureRef(index), ast.NumVal(value)) for index, value in enumerate(coef) ] return utils.apply_op_to_expressions(ast.BinNumOpType.ADD, ast.NumVal(intercept), *feature_weight_mul_ops)
def _negativebinomial_inversed(self, ast_to_transform): alpha = self._get_alpha() res = utils.sub( ast.NumVal(1.0), ast.ExpExpr(utils.sub(ast.NumVal(0.0), ast_to_transform))) return utils.div( ast.NumVal(-1.0), utils.mul(ast.NumVal(alpha), res) if alpha != 1.0 else res)
def log1p(expr): # Use trick to compute log1p for small values more accurate # https://www.johndcook.com/blog/2012/07/25/trick-for-computing-log1x/ expr = ast.IdExpr(expr, to_reuse=True) expr1p = utils.add(ast.NumVal(1.0), expr, to_reuse=True) expr1pm1 = utils.sub(expr1p, ast.NumVal(1.0), to_reuse=True) return ast.IfExpr( utils.eq(expr1pm1, ast.NumVal(0.0)), expr, utils.div(utils.mul(expr, ast.LogExpr(expr1p)), expr1pm1))
def _bin_class_sigmoid_transform(self, expr, to_reuse=True): coef = 1.0 for config_part in self.objective_config_parts: config_entry = config_part.split(":") if config_entry[0] == "sigmoid": coef = np.float64(config_entry[1]) break return super()._bin_class_convert_output( utils.mul(ast.NumVal(coef), expr) if coef != 1.0 else expr, to_reuse=to_reuse)
def _rbf_kernel(self, support_vector): elem_wise = [ ast.PowExpr( utils.sub(ast.NumVal(support_element), ast.FeatureRef(i)), ast.NumVal(2)) for i, support_element in enumerate(support_vector) ] kernel = utils.apply_op_to_expressions(ast.BinNumOpType.ADD, *elem_wise) kernel = utils.mul(self._neg_gamma_expr, kernel) return ast.ExpExpr(kernel)
def _negativebinomial_inversed(self, ast_to_transform): return utils.div( ast.NumVal(-1.0), utils.mul( ast.NumVal(self.model.model.family.link.alpha), utils.sub( ast.NumVal(1.0), ast.ExpExpr( utils.sub( ast.NumVal(0.0), ast_to_transform)))))
def tanh(expr): expr = ast.IdExpr(expr, to_reuse=True) tanh_expr = utils.sub( ast.NumVal(1.0), utils.div( ast.NumVal(2.0), utils.add(ast.ExpExpr(utils.mul(ast.NumVal(2.0), expr)), ast.NumVal(1.0)))) return ast.IfExpr( utils.gt(expr, ast.NumVal(44.0)), # exp(2*x) <= 2^127 ast.NumVal(1.0), ast.IfExpr(utils.lt(expr, ast.NumVal(-44.0)), ast.NumVal(-1.0), tanh_expr))
def _assemble_single_output(self): support_vectors = self.model.support_vectors_ coef = self.model.dual_coef_[0] intercept = self.model.intercept_[0] kernel_exprs = self._apply_kernel(support_vectors) kernel_weight_mul_ops = [] for index, value in enumerate(coef): kernel_weight_mul_ops.append( utils.mul(kernel_exprs[index], ast.NumVal(value))) return utils.apply_op_to_expressions(ast.BinNumOpType.ADD, ast.NumVal(intercept), *kernel_weight_mul_ops)
def _assemble_single_output(self, idx=0): support_vectors = self.model.support_vectors_ coef = self._get_single_coef(idx) intercept = self._get_single_intercept(idx) kernel_exprs = self._apply_kernel(support_vectors) kernel_weight_mul_ops = [ utils.mul(kernel_exprs[index], ast.NumVal(value)) for index, value in enumerate(coef) ] return utils.apply_op_to_expressions(ast.BinNumOpType.ADD, ast.NumVal(intercept), *kernel_weight_mul_ops)
def _cosine_kernel(self, support_vector): support_vector_norm = np.linalg.norm(support_vector) if support_vector_norm == 0.0: support_vector_norm = 1.0 feature_norm = ast.SqrtExpr(utils.apply_op_to_expressions( ast.BinNumOpType.ADD, *[ utils.mul(ast.FeatureRef(i), ast.FeatureRef(i)) for i in range(len(support_vector)) ]), to_reuse=True) safe_feature_norm = ast.IfExpr(utils.eq(feature_norm, ast.NumVal(0.0)), ast.NumVal(1.0), feature_norm) kernel = self._linear_kernel(support_vector / support_vector_norm) kernel = utils.div(kernel, safe_feature_norm) return kernel
def _linear_kernel_with_gama_and_coef(self, support_vector): kernel = self._linear_kernel(support_vector) kernel = utils.mul(self._gamma_expr, kernel) return utils.add(kernel, ast.NumVal(self.model.coef0))
def _linear_kernel(self, support_vector): elem_wise = [ utils.mul(ast.NumVal(support_element), ast.FeatureRef(i)) for i, support_element in enumerate(support_vector) ] return utils.apply_op_to_expressions(ast.BinNumOpType.ADD, *elem_wise)
def _maybe_sqr_transform(self, expr): if "sqrt" in self.objective_config_parts: expr = ast.IdExpr(expr, to_reuse=True) return utils.mul(ast.AbsExpr(expr), expr) else: return expr
def atan(expr): expr = ast.IdExpr(expr, to_reuse=True) expr_abs = ast.AbsExpr(expr, to_reuse=True) expr_reduced = ast.IdExpr(ast.IfExpr( utils.gt(expr_abs, ast.NumVal(2.4142135623730950488)), utils.div(ast.NumVal(1.0), expr_abs), ast.IfExpr( utils.gt(expr_abs, ast.NumVal(0.66)), utils.div(utils.sub(expr_abs, ast.NumVal(1.0)), utils.add(expr_abs, ast.NumVal(1.0))), expr_abs)), to_reuse=True) P0 = ast.NumVal(-8.750608600031904122785e-01) P1 = ast.NumVal(1.615753718733365076637e+01) P2 = ast.NumVal(7.500855792314704667340e+01) P3 = ast.NumVal(1.228866684490136173410e+02) P4 = ast.NumVal(6.485021904942025371773e+01) Q0 = ast.NumVal(2.485846490142306297962e+01) Q1 = ast.NumVal(1.650270098316988542046e+02) Q2 = ast.NumVal(4.328810604912902668951e+02) Q3 = ast.NumVal(4.853903996359136964868e+02) Q4 = ast.NumVal(1.945506571482613964425e+02) expr2 = utils.mul(expr_reduced, expr_reduced, to_reuse=True) z = utils.mul( expr2, utils.div( utils.sub( utils.mul( expr2, utils.sub( utils.mul( expr2, utils.sub( utils.mul(expr2, utils.sub(utils.mul(expr2, P0), P1)), P2)), P3)), P4), utils.add( Q4, utils.mul( expr2, utils.add( Q3, utils.mul( expr2, utils.add( Q2, utils.mul( expr2, utils.add( Q1, utils.mul(expr2, utils.add(Q0, expr2))))))))))) z = utils.add(utils.mul(expr_reduced, z), expr_reduced) ret = utils.mul( z, ast.IfExpr(utils.gt(expr_abs, ast.NumVal(2.4142135623730950488)), ast.NumVal(-1.0), ast.NumVal(1.0))) ret = utils.add( ret, ast.IfExpr( utils.lte(expr_abs, ast.NumVal(0.66)), ast.NumVal(0.0), ast.IfExpr(utils.gt(expr_abs, ast.NumVal(2.4142135623730950488)), ast.NumVal(1.570796326794896680463661649), ast.NumVal(0.7853981633974483402318308245)))) ret = utils.mul( ret, ast.IfExpr(utils.lt(expr, ast.NumVal(0.0)), ast.NumVal(-1.0), ast.NumVal(1.0))) return ret