Skip to content

Commit

Permalink
Added multi-armed bandit examples
Browse files Browse the repository at this point in the history
  • Loading branch information
cereallarceny committed Jul 10, 2020
1 parent 8d121ba commit ca459e0
Show file tree
Hide file tree
Showing 11 changed files with 7,473 additions and 8 deletions.
14 changes: 6 additions & 8 deletions examples/mnist/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Syft.js MNIST Example
# syft.js MNIST Example

This is a demonstration of how to use [syft.js](https://github.com/openmined/syft.js)
with [PyGrid](https://github.com/OpenMined/pygrid) to train a plan on local data in the browser.

Prerequisites:
## Quick Start

1. Execute `npm install`
2. Install and start [PyGrid](https://github.com/OpenMined/pygrid)
3. Install [PySyft](https://github.com/OpenMined/PySyft) and execute "Create Plan" and "Host Plan" notebooks from `examples/experimental/FL Training Plan` folder
to seed MNIST plan and model into PyGrid.

Finally, execute `npm start`.
1. Install and start [PyGrid](https://github.com/OpenMined/pygrid)
2. Install [PySyft](https://github.com/OpenMined/PySyft) and execute the "Part 01 - Create Plan" notebook from `examples/tutorials/static-fl` folder to seed the MNIST plan and model into PyGrid.
3. Now back in this folder, execute `npm install`
4. And then execute `npm start`

This will launch a web browser running the file `index.js`. Every time you make changes to this file, the server will automatically re-compile your code and refresh the page. No need to start and stop. :)
17 changes: 17 additions & 0 deletions examples/multi-armed-bandit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# syft.js Multi-armed Bandit Example

This is a demonstration of how to use [syft.js](https://github.com/openmined/syft.js)
with [PyGrid](https://github.com/OpenMined/pygrid) to train [a multi-armed bandit](https://vwo.com/blog/multi-armed-bandit-algorithm/) in the browser. A multi-armed bandit can be used to perform automated A/B testing on a website or application, while gradually converging your users to the ideal user-experience, given a goal of your choosing.

In this demo, we're automatically generating various website layouts that we want our users to view. There are subtle changes made to the website every time you load the website again, including things like changes in button size, color, or position on the page. In the background, syft.js will track which layouts the user does what we want (click a button) and report a positive model diff for that particular layout. For all other layouts where the user doesn't click on the button, we do not report anything. Over time, our model will slowly start to converge on a "preferred user experience" for the best layout, as chosen by user actions.

While this demo is inherently simple, it's easy to see how one could extend it to a real-world application whereby website layouts are generated and tested by real users, slowly converging to the preferred UX. We're particuarly excited to see derivations of this demo in real-world web and mobile development!

## Quick Start

1. Install and start [PyGrid](https://github.com/OpenMined/pygrid)
2. Install [PySyft](https://github.com/OpenMined/PySyft) and ... TODO: @maddie - fill this in here
3. Now back in this folder, execute `npm install`
4. And then execute `npm start`

This will launch a web browser running the file `index.js`. Every time you make changes to this file, the server will automatically re-compile your code and refresh the page. No need to start and stop. :)
241 changes: 241 additions & 0 deletions examples/multi-armed-bandit/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useEffect } from 'react';

import backgroundGradient from './background-gradient.svg';
import logoWhite from './logo-white.svg';
import logoColor from './logo-color.svg';

import '@fortawesome/fontawesome-free/js/all';

const fontFamily =
'"Rubik", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';

const globalStyles = {
paragraph: {
fontFamily,
lineHeight: 1.75,
fontSize: 18
},
heading: {
fontFamily,
lineHeight: 1.5,
textTransform: 'uppercase',
fontWeight: 700,
letterSpacing: 2,
marginTop: 0,
marginBottom: 0,
fontSize: 24
}
};

const Hero = ({ background, button }) => {
const title = 'Answer Questions Using Data You Cannot See';
const description = `OpenMined is an open-source community whose goal is to make the world more privacy-preserving by lowering the barrier-to-entry to private AI technologies.`;

const styles = {
container: {
background:
background === 'gradient' ? `url(${backgroundGradient})` : '#333',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
padding: 40,
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
logo: {
width: 200,
height: 'auto'
},
title: {
color: 'white',
marginTop: 40,
width: 480,
textAlign: 'center'
},
description: {
color: 'white',
marginTop: 40,
marginBottom: 0,
width: 480,
textAlign: 'center'
}
};

return (
<div css={styles.container}>
<img src={logoWhite} alt="OpenMined" css={styles.logo} />
<h2 css={{ ...globalStyles.heading, ...styles.title }}>{title}</h2>
<p css={{ ...globalStyles.paragraph, ...styles.description }}>
{description}
</p>
{button && button}
</div>
);
};

const Vision = ({ button }) => {
const title = 'Vision & Mission';
const description = `
<p>Industry standard tools for artificial intelligence have been designed with several assumptions: data is centralized into a single compute cluster, the cluster exists in a secure cloud, and the resulting models will be owned by a central authority. We envision a world in which we are not restricted to this scenario - a world in which AI tools treat privacy, security, and multi-owner governance as first class citizens.</p>
<p><b>With OpenMined, an AI model can be governed by multiple owners and trained securely on an unseen, distributed dataset.</b></p>
<p>The mission of the OpenMined community is to create an accessible ecosystem of tools for private, secure, multi-owner governed AI. We do this by extending popular libraries like TensorFlow and PyTorch with advanced techniques in cryptography and private machine learning.</p>
`;

const styles = {
container: {
padding: 40,
maxWidth: 960,
width: '90%',
margin: '0 auto'
}
};

return (
<div css={styles.container}>
<h4 css={globalStyles.heading}>{title}</h4>
<div
css={{ ...globalStyles.paragraph, marginBottom: -20 }}
dangerouslySetInnerHTML={{ __html: description }}
/>
{button && button}
</div>
);
};

const Button = ({ background, icon, onClick }) => (
<button
css={{
fontFamily,
textTransform: 'uppercase',
letterSpacing: 1,
fontWeight: 700,
fontSize: 16,
background: background === 'blue' ? '#62A4AE' : '#EEE',
color: background === 'blue' ? '#FAFAFA' : '#333',
appearance: 'none',
border: 0,
borderRadius: 4,
padding: '15px 20px',
marginTop: 40,
marginBottom: 0,
transition: 'background 0.2s ease-in-out',
cursor: 'pointer',
'&:hover': {
background: background === 'blue' ? '#498B95' : '#DDD'
},
'&:focus': {
outline: 0,
boxShadow: 0,
border: 0
}
}}
onClick={onClick}
>
<span css={{ marginRight: 60 }}>Sign Up</span>
{icon === 'arrow' && <i class="fas fa-arrow-right" />}
{icon === 'user' && <i class="fas fa-user-plus" />}
{icon === 'code' && <i class="fas fa-code" />}
</button>
);

const Footer = () => {
const styles = {
wrapper: {
background: '#333',
padding: 40
},
container: {
display: 'flex',
justifyContent: 'space-between',
width: 940,
margin: '0 auto'
},
logo: {
width: 200,
height: 'auto'
},
social: {
display: 'flex',
alignItems: 'center'
},
socialIcon: {
color: 'rgba(255, 255, 255, 0.5)',
transition: 'color 0.2s ease-in-out',
fontSize: 24,
marginLeft: 20,
'&:hover': {
color: '#FFF'
}
}
};
return (
<div css={styles.wrapper}>
<div css={styles.container}>
<img src={logoColor} alt="OpenMined" css={styles.logo} />
<div css={styles.social}>
<a
href="https://github.com/OpenMined"
target="_blank"
css={styles.socialIcon}
>
<i class="fab fa-github" />
</a>
<a
href="https://twitter.com/openminedorg"
target="_blank"
css={styles.socialIcon}
>
<i class="fab fa-twitter" />
</a>
<a
href="https://youtube.com/c/OpenMinedOrg"
target="_blank"
css={styles.socialIcon}
>
<i class="fab fa-youtube" />
</a>
<a
href="https://facebook.com/openminedorg"
target="_blank"
css={styles.socialIcon}
>
<i class="fab fa-facebook" />
</a>
</div>
</div>
</div>
);
};

export default ({ config, onButtonClick, start }) => {
useEffect(() => {
start();
}, []);

const button = (
<Button
background={config.buttonColor}
icon={config.buttonIcon}
onClick={onButtonClick}
/>
);

return (
<div
css={{
minHeight: '100vh',
display: 'grid',
gridTemplateRows: 'auto 1fr auto'
}}
>
<Hero
background={config.heroBackground}
button={config.buttonPosition === 'hero' ? button : null}
/>
<Vision button={config.buttonPosition === 'vision' ? button : null} />
<Footer />
</div>
);
};
1 change: 1 addition & 0 deletions examples/multi-armed-bandit/background-gradient.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions examples/multi-armed-bandit/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;1,500&display=swap"
rel="stylesheet"
/>

<style type="text/css">
body,
#root {
min-height: 100vh;
}
</style>

<title>Syft.js Multi-armed Bandit Example</title>

<!-- NOTE: TFJS version must match with one in package-lock.json -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2.5/dist/tf.min.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
Loading

0 comments on commit ca459e0

Please sign in to comment.