Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[demo] Add an option for word hashing vocab #91

Merged
merged 12 commits into from
Jun 17, 2020
2 changes: 2 additions & 0 deletions demo/.soliumignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This file is in the root folder for VS Code.

# Abstract contracts do not work yet: https://github.com/duaraghav8/Ethlint/issues/281
# grep -R --files-with-matches '^abstract contract' client/src/contracts/
client/src/contracts/classification/Classifier.sol
Expand Down
2 changes: 2 additions & 0 deletions demo/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@tensorflow-models/universal-sentence-encoder": "^1.2.0",
"@tensorflow/tfjs": "^1.3.2",
"@types/jest": "^24.0.23",
"@types/murmurhash-js": "^1.0.3",
"@types/node": "^12.12.14",
"@types/react": "^16.9.14",
"@types/react-dom": "^16.9.4",
Expand All @@ -21,6 +22,7 @@
"dotenv": "^8.2.0",
"immutability-helper": "^3.0.1",
"moment": "^2.24.0",
"murmurhash-js": "^1.0.0",
"notistack": "^0.9.7",
"react": "^16.12.0",
"react-addons-update": "^15.6.2",
Expand Down
68 changes: 37 additions & 31 deletions demo/client/src/components/addModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,42 @@ class AddModel extends React.Component {
onChange={this.handleInputChange}
/>

{/* Encoder */}
<Typography variant="h6" component="h6">
Encoder
</Typography>
<Typography component="p">
An encoder is the method that is used to convert the input (text, image, etc.) into a machine readable format.
</Typography>
<Select className={this.classes.selector}
onChange={this.handleInputChange}
value={this.state.encoder}
inputProps={{
name: 'encoder',
}}
>
<Tooltip value="none" placement="top-start"
title="No transformation will be applied">
<MenuItem>None</MenuItem>
</Tooltip>
<Tooltip value="MurmurHash3" placement="top-start"
title="Convert each word to a 32-bit number using MurmurHash3">
<MenuItem>MurmurHash3</MenuItem>
</Tooltip>
<Tooltip value="IMDB vocab" placement="top-start"
title="Convert each word in English text to a number using the 1000 most frequent words in the IMDB review dataset">
<MenuItem>IMDB vocab</MenuItem>
</Tooltip>
<Tooltip value="universal sentence encoder" placement="top-start"
title="Use Universal Sentence Encoder to convert English text to a vector of numbers">
<MenuItem>Universal Sentence Encoder (for English text)</MenuItem>
</Tooltip>
<Tooltip value="MobileNetv2" placement="top-start"
title="Use MobileNetv2 to convert images to a vector of numbers">
<MenuItem>MobileNetv2 (for images)</MenuItem>
</Tooltip>
</Select>

{/* Model */}
{/* Don't need to ask for the model type since there is only one option and in the future, it should be inferred from the provided file.
<InputLabel className={this.classes.selectorLabel} htmlFor="model-type">Model type</InputLabel>
Expand Down Expand Up @@ -307,36 +343,6 @@ class AddModel extends React.Component {
)}
</Dropzone>

{/* Encoder */}
<Tooltip placement="top-start"
title="The method that will be used to convert the input (text, image, etc.) into a machine readable format">
<InputLabel className={this.classes.selectorLabel} htmlFor="encoder">Encoder</InputLabel>
</Tooltip>
<Select className={this.classes.selector}
onChange={this.handleInputChange}
value={this.state.encoder}
inputProps={{
name: 'encoder',
}}
>
<Tooltip value="none" placement="top-start"
title="No transformation will be applied">
<MenuItem>None</MenuItem>
</Tooltip>
<Tooltip value="IMDB vocab" placement="top-start"
title="Convert each word in English text to a number using the 1000 most frequent words in the IMDB review dataset">
<MenuItem>IMDB vocab</MenuItem>
</Tooltip>
<Tooltip value="universal sentence encoder" placement="top-start"
title="Use Universal Sentence Encoder to convert English text to a vector of numbers">
<MenuItem>Universal Sentence Encoder (for English text)</MenuItem>
</Tooltip>
<Tooltip value="MobileNetv2" placement="top-start"
title="Use MobileNetv2 to convert images to a vector of numbers">
<MenuItem>MobileNetv2 (for images)</MenuItem>
</Tooltip>
</Select>

{/* Incentive Mechanism */}
<Tooltip placement="top-start"
title={"The system that will be used to determine rewards for data that is determined to be \"good\"."}>
Expand Down Expand Up @@ -387,7 +393,7 @@ class AddModel extends React.Component {
</Paper>
<Paper className={this.classes.root} elevation={1}>
<Typography component="h3">
Deployment Status
Deployment Status
</Typography>
<Table className={this.classes.table} aria-label="Deployment Information Table">
<TableHead>
Expand Down
20 changes: 16 additions & 4 deletions demo/client/src/components/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import * as tf from '@tensorflow/tfjs';
import loadImage from 'blueimp-load-image';
import update from 'immutability-helper';
import moment from 'moment';
import { murmur3 } from 'murmurhash-js';
import { withSnackbar } from 'notistack';
import PropTypes from 'prop-types';
import React from 'react';
Expand Down Expand Up @@ -316,7 +317,11 @@ class Model extends React.Component {
}

async setTransformInputMethod() {
if (this.state.contractInfo.encoder === 'universal sentence encoder') {
let { encoder } = this.state.contractInfo
if (encoder) {
encoder = encoder.toLocaleLowerCase('en')
}
if (encoder === 'universal sentence encoder') {
this.setState({ inputType: INPUT_TYPE_TEXT });
UniversalSentenceEncoder.load().then(use => {
this.transformInput = async (query) => {
Expand All @@ -335,7 +340,7 @@ class Model extends React.Component {
};
this.transformInput = this.transformInput.bind(this);
});
} else if (this.state.contractInfo.encoder === 'MobileNetv2') {
} else if (encoder === 'MobileNetv2'.toLocaleLowerCase('en')) {
this.setState({ inputType: INPUT_TYPE_IMAGE });
// https://github.com/tensorflow/tfjs-models/tree/master/mobilenet
mobilenet.load({
Expand All @@ -362,14 +367,14 @@ class Model extends React.Component {
}
this.transformInput = this.transformInput.bind(this);
});
} else if (this.state.contractInfo.encoder === 'IMDB vocab') {
} else if (encoder === 'IMDB vocab'.toLocaleLowerCase('en')) {
this.setState({ inputType: INPUT_TYPE_TEXT });
this.vocab = [];
Object.entries(ImdbVocab).forEach(([key, value]) => {
this.vocab[value] = key;
});
this.transformInput = async (query) => {
const tokens = query.toLowerCase().split(" ");
const tokens = query.toLocaleLowerCase('en').split(/\s+/)
return tokens.map(t => {
let idx = ImdbVocab[t];
if (idx === undefined) {
Expand All @@ -380,6 +385,13 @@ class Model extends React.Component {
}).map(v => this.web3.utils.toHex(v));
};
this.transformInput = this.transformInput.bind(this);
} else if (encoder === 'MurmurHash3'.toLocaleLowerCase('en')) {
this.setState({ inputType: INPUT_TYPE_TEXT })
this.transformInput = async (query) => {
const tokens = query.toLocaleLowerCase('en').split(/\s+/)
return tokens.map(murmur3).map(v => this.web3.utils.toHex(v));
};
this.transformInput = this.transformInput.bind(this);
} else {
throw new Error(`Couldn't find encoder for ${this.state.contractInfo.encoder}`);
}
Expand Down
16 changes: 6 additions & 10 deletions demo/client/src/containers/modelList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Button from '@material-ui/core/Button';
import CircularProgress from '@material-ui/core/CircularProgress';
import Container from '@material-ui/core/Container';
import IconButton from '@material-ui/core/IconButton';
import Link from '@material-ui/core/Link';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
Expand All @@ -10,7 +11,6 @@ import Modal from '@material-ui/core/Modal';
import Paper from '@material-ui/core/Paper';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import AddIcon from '@material-ui/icons/Add';
import ClearIcon from '@material-ui/icons/Clear';
import DeleteIcon from '@material-ui/icons/Delete';
import { withSnackbar } from 'notistack';
Expand Down Expand Up @@ -233,16 +233,12 @@ class ModelList extends React.Component {
</Typography>
<Typography component="p">
Here you will find models stored on a blockchain that you can interact with.
Models are added to this list if you have recorded them locally in this browser
Models are added to this list if you have recorded them on your device in this browser
{serviceStorageEnabled ? " or if they are listed on a centralized database" : ""}.
</Typography>
<div>
<Button className={this.props.classes.button} variant="outlined" color="primary"
href='/addDeployedModel'
>
<AddIcon />&nbsp;Use a deployed model not listed
</Button>
</div>
<Typography component="p">
You can deploy your own model <Link href='/addModel'>here</Link> or use an already deployed model by filling in the information <Link href='/addDeployedModel'>here</Link>.
</Typography>
</div>
{this.state.loadingModels ?
<div className={this.props.classes.spinnerDiv}>
Expand Down Expand Up @@ -277,7 +273,7 @@ class ModelList extends React.Component {
:
<div className={this.props.classes.descriptionDiv}>
<Typography component="p">
No models found.
You do not have any models listed.
</Typography>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract NaiveBayesClassifier is Classifier64 {
* @param _classifications The classifications supported by the model.
* @param _classCounts The number of occurrences of each class in the training data.
* @param _featureCounts For each class, the number of times each feature occurs within that class.
* Each innermost list is a tuple of the feature index and the number of times that feature occurs within the class.
* Each innermost array is a tuple of the feature index and the number of times that feature occurs within the class.
* @param _totalNumFeatures The total number of features throughout all classes.
* @param _smoothingFactor The smoothing factor (sometimes called alpha). Use toFloat (1 mapped) for Laplace smoothing.
*/
Expand Down Expand Up @@ -97,7 +97,8 @@ contract NaiveBayesClassifier is Classifier64 {
* Set feature counts for an existing classification.
* For efficiency, features are overriden them if they have already been set.
* Made to be called just after the contract is created and never again.
* @param _featureCounts The index to start placing `_weights` into the model's weights.
* @param _featureCounts The number of times each feature occurs.
* Each innermost array is a tuple of the feature index and the number of times that feature occurs within the class.
* @param classification The class to add counts to.
*/
function initializeCounts(uint32[][] memory _featureCounts, uint64 classification) public onlyOwner {
Expand Down
Loading