-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpredict.js
97 lines (84 loc) · 2.4 KB
/
predict.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// pull-streams
const pull = require('pull-stream')
const values = require('pull-stream/sources/values')
const drain = require('pull-stream/sinks/drain')
const onEnd = require('pull-stream/sinks/on-end')
const collect = require('pull-stream/sinks/collect')
const map = require('pull-stream/throughs/map')
const asyncMap = require('pull-stream/throughs/async-map')
const flatten = require('pull-stream/throughs/flatten')
const filter = require('pull-stream/throughs/filter')
const unique = require('pull-stream/throughs/unique')
const sort = require('pull-sort')
const db = require('./data')
const limdu = require('limdu')
const zip = require('lodash.zipobject')
const movieClassifier = new limdu.classifiers.multilabel.PassiveAggressive({
Constant: 5.0,
retrain_count: 10
})
predict()
function predict () {
db('movies')
.whereNotNull('tomato_meter')
.select()
.asCallback((err, rows) => {
pull(
values(rows),
asyncMap((movie, cb) => {
db('cast_crew')
.where('movie_id', movie.id)
.select()
.asCallback((err, credits) => {
cb(null, { movie, credits })
})
}),
map((d) => {
return movieClassifier.trainOnline(input(d.credits), output(d.movie))
}),
onEnd(() => {
rankCreatives(movieClassifier)
})
)
})
}
function rankCreatives (classifier) {
db('cast_crew').select().asCallback((err, credits) => {
pull(
values(credits),
unique((credit) => `${credit.job}-${credit.person_id}`),
map((credit) => {
const personRole = personKey(credit)
return {
personRole,
scores: classifier.classify({ [personRole]: 1 }, 0, true)
}
}),
map((result) => {
result.score = getTrueScore(result.scores)
delete result.scores
return result
}),
sort((a, b) => b.score - a.score),
collect((err, results) => {
console.log(results)
})
)
})
}
function getTrueScore (scores) {
if (scores[0][0] === 'true') return scores[0][1]
else return scores[1][1]
}
function personKey (credit) {
return `${credit.job}-${credit.name}-${credit.person_id}`
}
function input (credits) {
return zip(
credits.map((c) => `${c.job}-${c.name}-${c.person_id}`),
credits.map((c) => 1)
)
}
function output (movie) {
return movie.tomato_meter > 69
}