diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2018-06-03 02:25:34 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2018-06-03 02:25:34 +0200 |
| commit | 46fbedf0ad7b167a28daf2030e06f34480576394 (patch) | |
| tree | 81877c97f777a8d705d47bb97ac96e5fa244bd2b /app/client/modules | |
| parent | 2149eb581c35a93d41dbad6e3409c498b4bed804 (diff) | |
add results page
Diffstat (limited to 'app/client/modules')
| -rw-r--r-- | app/client/modules/samplernn/index.js | 3 | ||||
| -rw-r--r-- | app/client/modules/samplernn/samplernn.actions.js | 109 | ||||
| -rw-r--r-- | app/client/modules/samplernn/samplernn.datasets.js | 60 | ||||
| -rw-r--r-- | app/client/modules/samplernn/samplernn.loss.js | 10 | ||||
| -rw-r--r-- | app/client/modules/samplernn/samplernn.results.js | 108 |
5 files changed, 203 insertions, 87 deletions
diff --git a/app/client/modules/samplernn/index.js b/app/client/modules/samplernn/index.js index 7066942..e1c41d5 100644 --- a/app/client/modules/samplernn/index.js +++ b/app/client/modules/samplernn/index.js @@ -1,6 +1,7 @@ import { h, Component } from 'preact' import { Route, Link } from 'react-router-dom' import SampleRNNDatasets from './samplernn.datasets' +import SampleRNNResults from './samplernn.results' import SampleRNNInspect from './samplernn.inspect' import SampleRNNLoss from './samplernn.loss' @@ -9,8 +10,10 @@ function router () { <div> <Route exact path='/samplernn/graph/' component={SampleRNNLoss} /> <Route exact path='/samplernn/inspect/' component={SampleRNNInspect} /> + <Route exact path='/samplernn/datasets/' component={SampleRNNDatasets} /> <Route exact path='/samplernn/datasets/:id/' component={SampleRNNDatasets} /> <Route exact path='/samplernn/datasets/new/' component={SampleRNNDatasets} /> + <Route exact path='/samplernn/results/' component={SampleRNNResults} /> </div> ) } diff --git a/app/client/modules/samplernn/samplernn.actions.js b/app/client/modules/samplernn/samplernn.actions.js index 1a60719..e8f8251 100644 --- a/app/client/modules/samplernn/samplernn.actions.js +++ b/app/client/modules/samplernn/samplernn.actions.js @@ -12,16 +12,38 @@ export const load_directories = (id) => (dispatch) => { actions.socket.list_directory({ module: 'samplernn', dir: 'datasets' }), actions.socket.list_directory({ module: 'samplernn', dir: 'results' }), actions.socket.list_directory({ module: 'samplernn', dir: 'output' }), + load_loss()(dispatch), ]).then(res => { // console.log(res) - const [folders, files, tasks, datasets, results, output] = res + const [folders, files, tasks, datasets, results, output, lossReport] = res - const empty_dataset = (name) => ({ - name, - input: [], - checkpoints: [], - output: [], - }) + const unsortedFolder = { + id: 0, + name: 'unsorted', + datasets: [], + } + + const datasetLookup = {} + + const get_dataset = (name, folder=unsortedFolder, date) => { + const dataset = datasetLookup[name] || empty_dataset(name, folder) + if (date) { + dataset.date = dataset.date ? Math.max(+new Date(date), dataset.date) : +new Date(date) + } + return dataset + } + + const empty_dataset = (name, folder=unsortedFolder) => { + const dataset = { + name, + input: [], + checkpoints: [], + output: [], + } + datasetLookup[dataset.name] = dataset + folder.datasets.push(dataset) + return dataset + } // take all of the folders and put them in a lookup const folderLookup = folders.reduce((folderLookup, folder) => { @@ -29,11 +51,7 @@ export const load_directories = (id) => (dispatch) => { folder.datasets = [] return folderLookup }, { - 'unsorted': { - id: 0, - name: 'unsorted', - datasets: [], - } + unsorted: unsortedFolder }) // prepare the files by splitting into two groups @@ -41,61 +59,34 @@ export const load_directories = (id) => (dispatch) => { const ungeneratedFiles = files.filter(file => !file.generated) // build the initial dataset lookup table using the ungenerated files - const datasetLookup = ungeneratedFiles.reduce((datasetLookup, file) => { - file.checkpoints = [] + ungeneratedFiles.reduce((datasetLookup, file) => { if (! file.name) { file.name = (file.opt || {}).token || file.url - // datasetLookup[] = file } const name = (file.name || 'unsorted').split('.')[0] - if (! datasetLookup[name]) { - const dataset = empty_dataset(name) - datasetLookup[dataset.name] = dataset - dataset.input.push(file) - folderLookup[file.folder_id].datasets.push(dataset) - } - else { - datasetLookup[name].input.push(file) - } + const dataset = get_dataset(name, folderLookup[file.folder_id], unsortedFolder, file.date) + dataset.input.push(file) return datasetLookup - }, { - unsorted: empty_dataset('unsorted') - }) + }, datasetLookup) // go over the generated files and add addl datasets (if the files were deleted) generatedFiles.map(file => { const pair = file.name.split('.')[0].split('-') - let dataset = datasetLookup[pair[0]] - if (!dataset) { - dataset = empty_dataset(pair[0]) - datasetLookup[dataset.name] = dataset - folderLookup[file.folder_id].datasets.push(dataset) - } + const dataset = get_dataset(pair[0], folderLookup[file.folder_id], unsortedFolder, file.date) dataset.output.push(file) file.epoch = file.epoch || pair[1] }) - // console.log(datasets) const flatDatasets = datasets.filter(s => s.name.match(/(wav|aiff?|flac|mp3)$/) && !s.dir) const builtDatasets = datasets.filter(s => s.dir) builtDatasets.forEach(dir => { - let dataset = datasetLookup[dir.name] - if (! dataset) { - dataset = empty_dataset(dir.name) - datasetLookup[dataset.name] = dataset - folderLookup.unsorted.datasets.push(dataset) - } + const dataset = get_dataset(dir.name) dataset.isBuilt = true }) flatDatasets.forEach(file => { const name = file.name.split('.')[0] - let dataset = datasetLookup[name] - if (! dataset) { - dataset = empty_dataset(name) - datasetLookup[dataset.name] = dataset - folderLookup.unsorted.datasets.push(dataset) - } + const dataset = get_dataset(name, unsortedFolder, file.date) file.persisted = false dataset.input.push(file) }) @@ -107,14 +98,15 @@ export const load_directories = (id) => (dispatch) => { .map(s => s.split(':')) .filter(b => b.length && b[1]) .reduce((a,b) => (a[b[0]] = b[1]) && a, {}) - checkpoint.name = checkpoint.dataset || checkpoint.exp + checkpoint.name = checkpoint.name || checkpoint.dataset || checkpoint.exp checkpoint.date = s.date checkpoint.dir = s - let dataset = datasetLookup[checkpoint.dataset] - if (! dataset) { - dataset = empty_dataset(checkpoint.dataset) - datasetLookup[dataset.name] = dataset - folderLookup.unsorted.datasets.push(dataset) + checkpoint.persisted = false + const dataset = get_dataset(checkpoint.name, unsortedFolder, checkpoint.date) + const loss = lossReport[checkpoint.name] + if (loss) { + dataset.epoch = checkpoint.epoch = loss.length + checkpoint.training_loss = loss } dataset.checkpoints.push(checkpoint) return checkpoint @@ -122,14 +114,10 @@ export const load_directories = (id) => (dispatch) => { output.map(file => { const pair = file.name.split('.')[0].split('-') - let dataset = datasetLookup[pair[0]] - if (!dataset) { - dataset = empty_dataset(pair[0]) - datasetLookup[dataset.name] = dataset - folderLookup.unsorted.datasets.push(dataset) - } + const dataset = get_dataset(pair[0], unsortedFolder, file.date) file.persisted = false - file.epoch = file.epoch || pair[1].replace(/^\D+/, '') + file.epoch = parseInt(file.epoch || pair[1].replace(/^\D+/, '')) || 0 + dataset.epoch = Math.max(file.epoch, dataset.epoch || 0) dataset.output.push(file) }) @@ -156,7 +144,7 @@ export const load_directories = (id) => (dispatch) => { } export const load_loss = () => dispatch => { - actions.socket.run_script({ module: 'samplernn', activity: 'report' }) + return actions.socket.run_script({ module: 'samplernn', activity: 'report' }) .then(report => { const lossReport = {} report.stdout.split('\n\n').filter(a=>!!a).forEach(data => { @@ -175,6 +163,7 @@ export const load_loss = () => dispatch => { type: types.samplernn.load_loss, lossReport }) + return lossReport }) } diff --git a/app/client/modules/samplernn/samplernn.datasets.js b/app/client/modules/samplernn/samplernn.datasets.js index b6a12cc..aa729a5 100644 --- a/app/client/modules/samplernn/samplernn.datasets.js +++ b/app/client/modules/samplernn/samplernn.datasets.js @@ -1,6 +1,7 @@ import { h, Component } from 'preact' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' +import * as util from '../../util' import * as samplernnActions from './samplernn.actions' @@ -18,11 +19,15 @@ class SampleRNNDatasets extends Component { super() this.fileOptions = this.fileOptions.bind(this) this.pickFile = this.pickFile.bind(this) - let id = props.match.params.id + let id = props.match.params.id || localStorage.getItem('samplernn.last_id') if (! id && props.location.pathname.match(/\/new\//)) { id = 'new' + } else if (id) { + localStorage.setItem('samplernn.last_id', id) + } + if (id && (! props.samplernn.folder || props.samplernn.folder.id !== id)) { + props.actions.load_directories(id) } - props.actions.load_directories(id) } pickFile(file){ console.log('pick', file) @@ -50,28 +55,45 @@ class SampleRNNDatasets extends Component { </div> ) } - fetchURL(url) { - } render(){ const { samplernn } = this.props const folder = samplernn.folder if (!folder.name) return - console.log(folder) - const datasets = folder.datasets.map(dataset =>{ - console.log(dataset) + const { mapFn, sortFn } = util.sort.orderByFn('date desc') + const datasets = folder.datasets.map(mapFn).sort(sortFn).map(pair => { + const dataset = pair[1] return ( <div className='row dataset'> <div className='col'> - {!!dataset.input.length && <FileList files={dataset.input} className='input_files' fileListClassName='' rowClassName='input_file' />} + {!!dataset.input.length && + <FileList + files={dataset.input} + className='input_files' + fileListClassName='' + rowClassName='input_file' + /> + } </div> <div className='col quiet'> - <div>{dataset.isBuilt ? 'has dataset' : 'not built'}</div> + <div>{dataset.isBuilt ? 'cached' : ''}</div> </div> <div className='col checkpoint'> - {!!dataset.checkpoints.length && <FileRow file={dataset.checkpoints[0]} />} + {!!dataset.checkpoints.length && + <FileRow + file={dataset.checkpoints[0]} + fields={'name date epoch'} + className='row checkpoint' + /> + } </div> <div className='col'> - {!!dataset.output.length && <FileList files={dataset.output} orderBy='epoch desc' />} + {!!dataset.output.length && + <FileList + files={dataset.output} + orderBy='epoch desc' + fields={'name date epoch size'} + /> + } </div> </div> ) @@ -79,12 +101,12 @@ class SampleRNNDatasets extends Component { return ( <div className='app'> <div className='heading'> - <h3>SampleRNN</h3> + <h2>SampleRNN</h2> </div> <div class='rows params datasets'> <div class='row dataset'> <div class='col'>input</div> - <div class='col'>dataset</div> + <div class='col'></div> <div class='col'>checkpoint</div> <div class='col'>output</div> </div> @@ -95,18 +117,6 @@ class SampleRNNDatasets extends Component { } } -// <Dataset -// canRename -// canUpload -// canAddURL -// canDeleteFile -// linkFiles -// fileOptions={this.fileOptions} -// onPick={this.handlePick} -// folder={samplernn.folder} -// files={samplernn.folder.files} -// /> - const mapStateToProps = state => ({ samplernn: state.module.samplernn, runner: state.system.runner, diff --git a/app/client/modules/samplernn/samplernn.loss.js b/app/client/modules/samplernn/samplernn.loss.js index 3900c31..04d16c8 100644 --- a/app/client/modules/samplernn/samplernn.loss.js +++ b/app/client/modules/samplernn/samplernn.loss.js @@ -95,9 +95,15 @@ class SampleRNNLoss extends Component { // if ( (ii % 1) < 0.1) { // ctx.strokeStyle = 'rgba(255,255,255,1.0)' ctx.lineWidth = 2 + ctx.setLineDash([4, 4]) ctx.stroke() + ctx.stroke() ctx.stroke() - ctx.stroke() + ctx.setLineDash([0,0]) + const fontSize = 12 + ctx.font = 'italic ' + (fontSize * devicePixelRatio) + 'px "Georgia"' + ctx.fill = 'black' + ctx.fillText(ii.toFixed(1), w-50, (h-Y) + fontSize + (10 * devicePixelRatio)) // } } ctx.lineWidth = 1 @@ -106,7 +112,7 @@ class SampleRNNLoss extends Component { const loss = lossReport[key] const vf = parseFloat(loss[loss.length-1].training_loss) || 0 const vg = parseFloat(loss[0].training_loss) || 5 - console.log(vf) + // console.log(vf) const vv = 1 - norm(vf, scaleMin, scaleMax/2) ctx.lineWidth = (1-norm(vf, scaleMin, scaleMax)) * 5 ctx.strokeStyle = 'rgba(' + [randrange(30,190), randrange(30,150), randrange(60,120)].join(',') + ',' + 0.8+ ')' diff --git a/app/client/modules/samplernn/samplernn.results.js b/app/client/modules/samplernn/samplernn.results.js new file mode 100644 index 0000000..518864b --- /dev/null +++ b/app/client/modules/samplernn/samplernn.results.js @@ -0,0 +1,108 @@ +import { h, Component } from 'preact' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import * as util from '../../util' + +import * as samplernnActions from './samplernn.actions' + +import Dataset from '../../dataset/dataset.component' + +import Group from '../../common/group.component' +import Slider from '../../common/slider.component' +import Select from '../../common/select.component' +import Button from '../../common/button.component' +import { FileList, FileRow } from '../../common/fileList.component' +import TextInput from '../../common/textInput.component' + +class SampleRNNResults extends Component { + constructor(props){ + super() + this.fileOptions = this.fileOptions.bind(this) + this.pickFile = this.pickFile.bind(this) + let id = props.match.params.id || localStorage.getItem('samplernn.last_id') + if (!props.samplernn.data) props.actions.load_directories() + } + pickFile(file){ + console.log('pick', file) + } + fileOptions(file){ + if (file.activity === 'url' && !file.dataset) { + if (this.props.runner.cpu.status !== 'IDLE') { + return ( + <div className='gray'> + fetching... + </div> + ) + } else { + return ( + <div className='link' onClick={() => this.fetchURL(file.url)}> + fetch + </div> + ) + } + } + return ( + <div> + <div className='link' onClick={() => this.train(file)}>train</div> + {file.epoch == 0 && <div className='epochs'>{file.epochs} ep.</div>} + </div> + ) + } + render(){ + if (this.props.samplernn.loading) return <span>Loading</span> + console.log(this.props.samplernn.data) + const { folderLookup } = this.props.samplernn.data + // const { folderLookup } = samplernn + console.log(this.props) + + const renders = Object.keys(folderLookup).sort(util.sort.stringSort.asc).map(key => { + const folder = folderLookup[key] + let { mapFn, sortFn } = util.sort.orderByFn('epoch desc') + console.log(mapFn, sortFn) + const datasetPairs = folder.datasets.map(mapFn).sort(sortFn) + const bestRenders = datasetPairs + .map(pair => pair[1]) + .filter(dataset => dataset.output.length) + .map(dataset => { + const { output } = dataset + return output.map(mapFn).sort(sortFn)[0][1] + }) + console.log(bestRenders.map(r => r.epoch)) + return ( + <div className='col'> + <h3>{key}</h3> + {!!bestRenders.length && + <FileList + files={bestRenders} + orderBy='epoch desc' + fields={'name date epoch size'} + /> + } + </div> + ) + }) + + return ( + <div className='app'> + <div className='heading'> + <h2>SampleRNN</h2> + </div> + <div class='rows params renders'> + {renders} + </div> + </div> + ) + } +} + +const mapStateToProps = state => ({ + samplernn: state.module.samplernn, + runner: state.system.runner, + task: state.task, +}) + +const mapDispatchToProps = (dispatch, ownProps) => ({ + actions: bindActionCreators(samplernnActions, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(SampleRNNResults) |
