How to render a confusion matrix visualization in a Kubeflow pipeline component step? - kubeflow

Here is what I am trying from one of the official tutorials
import kfp
import kfp.dsl as dsl
from kfp.components import create_component_from_func
#create_component_from_func
def confusion_visualization(matrix_uri: str = 'https://raw.githubusercontent.com/kubeflow/pipelines/master/samples/core/visualization/confusion_matrix.csv') -> NamedTuple('VisualizationOutput', [('mlpipeline_ui_metadata', 'UI_metadata')]):
"""Provide confusion matrix csv file to visualize as metrics."""
import json
metadata = {
'outputs' : [{
'type': 'confusion_matrix',
'format': 'csv',
'schema': [
{'name': 'target', 'type': 'CATEGORY'},
{'name': 'predicted', 'type': 'CATEGORY'},
{'name': 'count', 'type': 'NUMBER'},
],
'source': matrix_uri,
'labels': ['rose', 'lily', 'iris'],
}]
}
print('Printing the metadata')
print(metadata)
from collections import namedtuple
visualization_output = namedtuple('VisualizationOutput', [
'mlpipeline_ui_metadata'])
print()
return visualization_output(json.dumps(metadata))
#dsl.pipeline(
name='confusion-matrix-pipeline',
description='A sample pipeline to generate Confusion Matrix for UI visualization.'
)
def confusion_matrix_pipeline():
confusion_visualization_task = confusion_visualization('results.json')
client = kfp.Client()
client.create_run_from_pipeline_func(
confusion_matrix_pipeline,
arguments={}
)
I am not able to see a visualization in neither of the Run output or Visualizations tab. It says there are no visualizations in this step. What am I missing here?

I think an issue with your code is that you don't provide the output as a file (try using an OutputPath).
From Kubeflow docs:
The component must also export a file output artifact with an artifact
name of mlpipeline-ui-metadata, or else the Kubeflow Pipelines UI will
not render the visualization.
...
If the component writes such a file to its container filesystem, the
Kubeflow Pipelines system extracts the file, and the Kubeflow
Pipelines UI uses the file to generate the specified viewer(s). The
metadata specifies where to load the artifact data from. The Kubeflow
Pipelines UI loads the data into memory and renders it.
The Kubeflow docs also provide an example, which is working for me:
def confusion_matrix_viz(mlpipeline_ui_metadata_path: kfp.components.OutputPath()):
import json
metadata = {
'outputs' : [{
'type': 'confusion_matrix',
'format': 'csv',
'schema': [
{'name': 'target', 'type': 'CATEGORY'},
{'name': 'predicted', 'type': 'CATEGORY'},
{'name': 'count', 'type': 'NUMBER'},
],
'source': <CONFUSION_MATRIX_CSV_FILE>,
# Convert vocab to string because for bealean values we want "True|False" to match csv data.
'labels': list(map(str, vocab)),
}]
}
with open(mlpipeline_ui_metadata_path, 'w') as metadata_file:
json.dump(metadata, metadata_file)
Accordingly, you might try modifying your code like so:
import kfp
import kfp.dsl as dsl
from kfp.components import create_component_from_func
#create_component_from_func
def confusion_visualization(
matrix_uri: str = 'https://raw.githubusercontent.com/kubeflow/pipelines/master/samples/core/visualization/confusion_matrix.csv',
mlpipeline_ui_metadata_path: kfp.components.OutputPath()
):
"""Provide confusion matrix csv file to visualize as metrics."""
import json
metadata = {
'outputs' : [{
'type': 'confusion_matrix',
'format': 'csv',
'schema': [
{'name': 'target', 'type': 'CATEGORY'},
{'name': 'predicted', 'type': 'CATEGORY'},
{'name': 'count', 'type': 'NUMBER'},
],
'source': matrix_uri,
'labels': ['rose', 'lily', 'iris'],
}]
}
print('Printing the metadata')
print(metadata)
with open(mlpipeline_ui_metadata_path, 'w') as metadata_file:
json.dump(metadata, metadata_file)
#dsl.pipeline(
name='confusion-matrix-pipeline',
description='A sample pipeline to generate Confusion Matrix for UI visualization.'
)
def confusion_matrix_pipeline():
confusion_visualization_task = confusion_visualization('results.json')
client = kfp.Client()
client.create_run_from_pipeline_func(
confusion_matrix_pipeline,
arguments={}
)

Related

Rollup with Gulp.js - Multiple outputs

I'm trying to use an array of outputs using Rollup on Gulp.
The documentation only shows a basic example with a single output file. (Although it states that the output property can contain an array)
.then(bundle => {
return bundle.write({
file: './dist/library.js',
format: 'umd',
name: 'library',
sourcemap: true
});
});
If I replace that for an array, it will fail:
.then(bundle => {
return bundle.write({
file: './dist/library.js',
format: 'umd',
name: 'library',
sourcemap: true
},
{
file: './dist/file2.js',
format: 'umd',
});
});
Error: You must specify "output.file" or "output.dir" for the build.
at error (/Users/alvarotrigolopez/Sites/extensions/experiments/bundle/node_modules/rollup/dist/shared/rollup.js:158:30)
at handleGenerateWrite (/Users/alvarotrigolopez/Sites/extensions/experiments/bundle/node_modules/rollup/dist/shared/rollup.js:23403:20)
I've tried using the output option as well and using #rollup/stream instead of just rollup.
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var rollup = require('#rollup/stream');
gulp.task('js', function() {
return rollup({
input: './app.js',
output: [
{
file: 'bundle.js',
format: 'umd',
},
{
file: 'test.js',
format: 'umd',
}
]
})
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(gulp.dest('./build/js'));
});
Unknown output options: 0, 1. Allowed options: amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, entryFileNames, esModule, exports, extend, externalLiveBindings, file, footer, format, freeze, generatedCode, globals, hoistTransitiveImports, indent, inlineDynamicImports, interop, intro, manualChunks, minifyInternalExports, name, namespaceToStringTag, noConflict, outro, paths, plugins, preferConst, preserveModules, preserveModulesRoot, sanitizeFileName, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict, systemNullSetters, validate

Artifactory and Jenkins - get file with newest/biggest custom property

I have generic repository "my_repo". I uploaded files there from jenkins with to paths like my_repo/branch_buildNumber/package.tar.gz and with custom property "tag" like "1.9.0","1.10.0" etc. I want to get item/file with latest/newest tag.
I tried to modify Example 2 from this link ...
https://www.jfrog.com/confluence/display/JFROG/Using+File+Specs#UsingFileSpecs-Examples
... and add sorting and limit the way it was done here ...
https://www.jfrog.com/confluence/display/JFROG/Artifactory+Query+Language#ArtifactoryQueryLanguage-limitDisplayLimitsandPagination
But im getting "unknown property desc" error.
The Jenkins Artifactory Plugin, like most of the JFrog clients, supports File Specs for downloading and uploading generic files.
The File Specs schema is described here. When creating a File Spec for downloading files, you have the option of using the "pattern" property, which can include wildcards. For example, the following spec downloads all the zip files from the my-local-repo repository into the local froggy directory:
{
"files": [
{
"pattern": "my-local-repo/*.zip",
"target": "froggy/"
}
]
}
Alternatively, you can use "aql" instead of "pattern". The following spec, provides the same result as the previous one:
{
"files": [
{
"aql": {
"items.find": {
"repo": "my-local-repo",
"$or": [
{
"$and": [
{
"path": {
"$match": "*"
},
"name": {
"$match": "*.zip"
}
}
]
}
]
}
},
"target": "froggy/"
}
]
}
The allowed AQL syntax inside File Specs does not include everything the Artifactory Query Language allows. For examples, you can't use the "include" or "sort" clauses. These limitations were put in place, to make the response structure known and constant.
Sorting however is still available with File Specs, regardless of whether you choose to use "pattern" or "aql". It is supported throw the "sortBy", "sortOrder", "limit" and "offset" File Spec properties.
For example, the following File Spec, will download only the 3 largest zip file files:
{
"files": [
{
"aql": {
"items.find": {
"repo": "my-local-repo",
"$or": [
{
"$and": [
{
"path": {
"$match": "*"
},
"name": {
"$match": "*.zip"
}
}
]
}
]
}
},
"sortBy": ["size"],
"sortOrder": "desc",
"limit": 3,
"target": "froggy/"
}
]
}
And you can do the same with "pattern", instead of "aql":
{
"files": [
{
"pattern": "my-local-repo/*.zip",
"sortBy": ["size"],
"sortOrder": "desc",
"limit": 3,
"target": "local/output/"
}
]
}
You can read more about File Specs here.
(After answering this question here, we also updated the File Specs documentation with these examples).
After a lot of testing and experimenting i found that there are many ways of solving my main problem (getting latest version of package) but each of way require some function which is available in paid version. Like sort() in AQL or [RELEASE] in REST API. But i found that i still can get JSON with a full list of files and its properties. I can also download each single file. This led me to solution with simple python script. I can't publish whole but only the core which should bu fairly obvious
import requests, argparse
from packaging import version
...
query="""
items.find({
"type" : "file",
"$and":[{
"repo" : {"$match" : \"""" + args.repository + """\"},
"path" : {"$match" : \"""" + args.path + """\"}
}]
}).include("name","repo","path","size","property.*")
"""
auth=(args.username,args.password)
def clearVersion(ver: str):
new = ''
for letter in ver:
if letter.isnumeric() or letter == ".":
new+=letter
return new
def lastestArtifact(response: requests):
response = response.json()
latestVer = "0.0.0"
currentItemIndex = 0
chosenItemIndex = 0
for results in response["results"]:
for prop in results['properties']:
if prop["key"] == "tag":
if version.parse(clearVersion(prop["value"])) > version.parse(clearVersion(latestVer)):
latestVer = prop["value"]
chosenItemIndex = currentItemIndex
currentItemIndex += 1
return response["results"][chosenItemIndex]
req = requests.post(url,data=query,auth=auth)
if args.verbose:
print(req.text)
latest = lastestArtifact(req)
...
I just want to point that THIS IS NOT permanent solution. We just didnt want to buy license yet only because of one single problem. But if there will be more of such problems then we definetly buy PRO subscription.

python api of google adwords(googleads) is giving "INVALID_CONVERSION_TYPE" when calling the OfflineConversionAdjustmentFeed operation

I am using googleads API to perform the following operations:
- (1) upload new conversions
- (2) adjust uploaded conversions
The first operation could be done successfuly.
However the second opeartion which is the adjustment of the uploaded conversion is giving the error "INVALID_CONVERSION_TYPE".
According to the documentation in https://developers.google.com/adwords/api/docs/reference/v201809/OfflineConversionFeedService.OfflineConversionError#reason.
The reason for this error is that the conversion name does not match any uploaded conversion for the same customer,
although i have uploaded the conversion with the same conversion name for the same customer.
I am posting my request and the response i am receiving:
request=[{
'operator': 'ADD',
'operand':
{
'adjustmentTime': '20190802 235959 Etc/GMT',
'googleClickId': 'gcliID',
'adjustedValueCurrencyCode': 'EUR',
'conversionName': 'YY',
'adjustedValue': xx,
'xsi_type': 'GclidOfflineConversionAdjustmentFeed',
'conversionTime': '20190731 235959 Etc/GMT',
'adjustmentType': 'RESTATE'
}
}
]
response = {
'ListReturnValue.Type': 'OfflineConversionAdjustmentFeedReturnValue',
'value': [
{
'conversionName': None,
'adjustmentTime': None,
'adjustmentType': None,
'adjustedValue': None,
'adjustedValueCurrencyCode': None,
'OfflineConversionAdjustmentFeed.Type': 'GclidOfflineConversionAdjustmentFeed',
'googleClickId': None,
'conversionTime': None
}
],
'partialFailureErrors': [
{
'fieldPath': 'operations[0].operand.conversionName',
'fieldPathElements': [
{
'field': 'operations',
'index': 0L
},
{
'field': 'operand',
'index': None
},
{
'field': 'conversionName',
'index': None
}
],
'trigger': None,
'errorString': 'OfflineConversionAdjustmentError.INVALID_CONVERSION_TYPE',
'ApiError.Type': 'OfflineConversionAdjustmentError',
'reason': 'INVALID_CONVERSION_TYPE'
}
]
}
Have you ever solved this issue? I'm having the very same one. The only solution I could find is not to use gclid, but switched to orderId - now adjustment works for me.

how to share rollup config files

I have 2 rollup config files which has some common parts and uncommon parts:
// rollup.config.umd.js
export config {
external: ['invariant', 'lodash'],
globals: {
invariant: 'invariant'
},
input: 'src/index.js',
name: 'my.comp',
output: {
file: 'my.comp.umd.js'
format: 'umd'
}...
and another file
// rollup.config.esm5.js
export config {
external: ['invariant', 'lodash'],
globals: {
invariant: 'invariant'
},
input: 'src/index.js',
name: 'my.comp',
output: {
file: 'my.comp.es5.js'
format: 'es'
}...
How do I keep these config files DRY ?
Not keeping DRY has following problems e.g. Imagine many external dependencies - if one forgets to add a new dependency in one place we are in trouble.
(I also use some different set of plugins etc and plugin configs but say that is out of scope of this problem.)
Firstly, they're just JavaScript modules, so you can always do this sort of thing:
// rollup.config.common.js
export default {
external: ['invariant', 'lodash'],
globals: {
invariant: 'invariant'
},
input: 'src/index.js',
name: 'my.comp'
};
// rollup.config.esm5.js
import common from './rollup.config.common.js';
export default Object.assign({
output: {
file: 'my.comp.es5.js'
format: 'es'
}
}, common);
// rollup.config.umd.js
import common from './rollup.config.common.js';
export default Object.assign({
output: {
file: 'my.comp.umd.js'
format: 'umd'
}
}, common);
But the real answer here is to combine the two configs into a single one like so:
export default {
external: ['invariant', 'lodash'],
globals: {
invariant: 'invariant'
},
input: 'src/index.js',
name: 'my.comp',
output: [
{
file: 'my.comp.es5.js'
format: 'es'
},
{
file: 'my.comp.umd.js'
format: 'umd'
}
]
};
As well as being simpler and easier to maintain, this will be faster, because Rollup can save doing a lot of the work twice.
If you need to change more than the output option between builds, you can also export an array of configs from a single file (export default [...]).

Travis CI - Builds are timing out

My .travis.yml
language: node_js
node_js:
- "0.12"
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
I have only added a few very simple tests so far (checking that class attributes exist).
I can see the tests are executed.
Then, the last few lines in the Travis output are this:
WARN [web-server]: 404: /css/style.min.css?1435068425.642
No output has been received in the last 10 minutes, this potentially indicates a stalled build or something wrong with the build itself.
The build has been terminated
If the tests are running, then the build and dependencies must have been installed already?
So why is the process not finishing once all tests are executed?
karma.config:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: [
'jasmine',
'requirejs'
],
// list of files / patterns to load in the browser
files: [
{pattern: 'js/vendor/**/*.js', included: false},
{pattern: 'js/*.js', watched: true, included: false},
{pattern: 'test/**/*Spec.js', watched: true, included: false},
{pattern: 'css/**/*.css', included: false},
'test/test-main.js'
],
// list of files to exclude
exclude: [
'test/lib/**/*.js',
'js/vendor/**/test/*.js', //do not include the vendor tests
'js/_admin.js'
],
preprocessors: {
},
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Firefox'], //'Chrome', 'PhantomJS', 'PhantomJS_custom'
singleRun: false,
});//config.set
};//module.exports
test-main.js in folder test:
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
//console.log('test files:', allTestFiles);
});
require.config({
baseUrl: '/base',
paths: {
'jquery': './js/vendor/jquery/jquery-2.1.4.min',
'jquery-ui': './js/vendor/jquery-ui-1.11.4.custom/jquery-ui.min',
'underscore': './js/vendor/underscore/underscore-min',
'backbone': './js/vendor/backbone/backbone-min',
'mustache': './js/vendor/mustache/mustache.min',
'domReady': './js/vendor/requirejs/plugins/domReady/domReady',
'text': './js/vendor/requirejs/plugins/text/text',
//------------------------------------
//custom requireJS application modules
'my': './js/my',
'my-CSS': './js/my-CSS'
},
shim: {
'underscore': {
exports: '_'
}
},
deps: allTestFiles,
callback: window.__karma__.start
});
The my-CSS module loads the css like this:
//custom requireJS module to hold the crowdUI class
define(["my"], function (my) { //prerequisites
'use strict';
//load the CSS definitions
document.head.appendChild(
my.createElement('link', {
attribute: {
id: 'my-CSS',
href: './css/style.min.css?' + crowdUI.TIMESTAMP,
rel: 'stylesheet',
type: 'text/css'
}
})
);
});
If the issue is just that your task requires more than 10 minutes during which it produces no output, the fix is simple: prepend your command with travis_wait.
For instance travis_wait myCommand instead of just myCommand.

Resources