-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from Azure-Samples/tyclintw/add-workshop-demo
Initial commit of the workshop demo
- Loading branch information
Showing
3 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Real World Reinforcement Learning Workshop | ||
|
||
## Abstract | ||
Microsoft recently announced the Azure Cognitive Service, Personalizer, aimed at democratizing real world reinforcement learning for content personalization. Its goal is to make reinforcement learning accessible to everyone, not just machine learning experts. Personalizer is the result of a successful partnership between Microsoft Research and Azure Cognitive Services aimed at rapid technology transfer and innovation. | ||
|
||
In this workshop you will learn the theory behind contextual bandits and how this applies to content personalization. We will walk you through setting up the service, writing your first application, and optimizing the policy using offline optimization. | ||
|
||
## Workshop Instructions | ||
1. [Create free Azure/Microsoft account](https://azure.microsoft.com/en-us/free/) | ||
2. Provision free instance of Personalizer | ||
1. Go to [Azure Portal](https://portal.azure.com) | ||
2. Search for "Cogitive Services" | ||
3. On Cognitive Services page click "Add" | ||
4. Search for "Personalizer" and click "Create" | ||
3. Install Python Client | ||
```pip install azure.cognitiveservices.personalizer``` | ||
3. Paste your endpoint into [line 34 of ./demo/demo.py](https://github.com/Azure-Samples/cognitive-services-personalizer-samples/blob/master/demos/workshop-demo/demo.py#L34) | ||
4. Paste your key into [line 35 of ./demo/demo.py](https://github.com/Azure-Samples/cognitive-services-personalizer-samples/blob/master/demos/workshop-demo/demo.py#L35) | ||
5. run `python ./demo/demo.py` | ||
|
||
## Next steps | ||
- [Personalizer](https://azure.microsoft.com/en-us/services/cognitive-services/personalizer/) | ||
- [Personalizer docs](https://docs.microsoft.com/en-us/azure/cognitive-services/personalizer/) | ||
- How can personalization be integrated into what you work on day to day? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
from azure.cognitiveservices.personalizer import PersonalizerClient | ||
import azure.cognitiveservices.personalizer.models as models | ||
from msrest.authentication import CognitiveServicesCredentials | ||
from helpers import SlidingAverage | ||
|
||
from datetime import datetime | ||
from random import randint | ||
|
||
def run(user_preference, actions, client, duration_sec): | ||
start = datetime.now() | ||
ctr = SlidingAverage(window_size = 20) | ||
while (datetime.now() - start).total_seconds() < duration_sec: | ||
index = randint(0, len(user_preference) - 1) | ||
|
||
user = user_preference[index][0] | ||
preference = user_preference[index][1] | ||
|
||
request=models.RankRequest( | ||
context_features=user, | ||
actions=actions | ||
) | ||
response=client.rank(request) | ||
reward = 1.0 if response.reward_action_id==preference else 0.0 | ||
client.events.reward(event_id=response.event_id, value=reward) | ||
|
||
ctr.update(reward) | ||
print('CTR: ' + str(ctr.get())) | ||
for action in response.ranking: | ||
print(action.id + ': ' + str(action.probability)) | ||
|
||
|
||
def main(): | ||
|
||
client = PersonalizerClient(endpoint="", # Put your endpoint here | ||
credentials=CognitiveServicesCredentials("")) # Put your credentials here | ||
|
||
#Available content | ||
actions=[ | ||
models.RankableAction( | ||
id='politics', | ||
features=[{'topic': 'politics'}]), | ||
models.RankableAction( | ||
id='sports', | ||
features=[{'topic': 'sports'}]), | ||
models.RankableAction( | ||
id='music', | ||
features=[{'topic': 'music'}] | ||
)] | ||
|
||
#User features | ||
Tom = {'name': 'Tom'} | ||
Anna = {'name': 'Anna'} | ||
|
||
#Time features | ||
Monday = {'day': 'Monday'} | ||
Sunday = {'day': 'Sunday'} | ||
|
||
context = [Tom, Monday] | ||
|
||
request=models.RankRequest( | ||
context_features=context, | ||
actions=actions | ||
) | ||
|
||
response=client.rank(request) | ||
# Show content to user, evaluate and provide reward back to service | ||
reward = 1.0 | ||
client.events.reward(event_id=response.event_id, value=reward) | ||
|
||
# Since we are doing cold start and there is no model, all probabilities are the same | ||
for action in response.ranking: | ||
print(action.id + ': ' + str(action.probability)) | ||
|
||
|
||
# Tom and Anna have certain preferences what to read on Monday and Sunday | ||
scenario = [([Tom, Monday], 'politics'), | ||
([Tom, Sunday], 'music'), | ||
([Anna, Monday], 'sports'), | ||
([Anna, Sunday], 'politics')] | ||
|
||
run(scenario, actions, client, 5400) | ||
|
||
# Olympics started and both Tom and Anna are following sport news during weekend | ||
scenario = [([Tom, Monday], 'politics'), | ||
([Tom, Sunday], 'sports'), | ||
([Anna, Monday], 'sports'), | ||
([Anna, Sunday], 'sports')] | ||
run(scenario, actions, client, 5400) | ||
|
||
if __name__== '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
class SlidingAverage: | ||
def __init__(self, window_size): | ||
self.index = 0 | ||
self.values = [0] * window_size | ||
|
||
def _previous(self): | ||
return self.values[(self.index + len(self.values) - 1) % len(self.values)] | ||
|
||
def update(self, value): | ||
self.values[self.index] = self._previous() + value | ||
self.index = (self.index + 1) % len(self.values) | ||
|
||
def get(self): | ||
return (self._previous() - self.values[self.index]) / (len(self.values) - 1) |