Skip to content

Commit

Permalink
Merge pull request #74 from CPSSD/kirill/yelp-search
Browse files Browse the repository at this point in the history
 Added term weights and slight deisgn update
  • Loading branch information
KirillSloka authored Nov 18, 2018
2 parents 8a43307 + e3c38e6 commit a4437da
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 108 deletions.
5 changes: 2 additions & 3 deletions LUCAS/app/lucas.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys
from flask import Flask
from flask import request
from flask import jsonify
from flask import json
from sklearn.externals import joblib
from os.path import dirname, join, abspath
Expand All @@ -20,7 +19,7 @@ def classify_review(review):
predicted_class = get_classification(model, review)
class_confidence = get_confidence(model, review)
feature_weights = get_feature_weights(model, review)
return{"result": predicted_class, "confidence": class_confidence, "feature_weights": feature_weights}
return{"result": predicted_class, "confidence": class_confidence, "feature_weights": feature_weights, "review": review}

@app.route('/classify', methods=['POST'])
def classify():
Expand All @@ -32,7 +31,7 @@ def bulkClassify():
weights = []
for review in request.get_json()["reviews"]:
weights.append(classify_review(review["text"]))
return jsonify(weights= weights)
return json.dumps(weights, sort_keys=False)

def start():
app.run(debug=True,host='0.0.0.0', port=3005)
Expand Down
2 changes: 1 addition & 1 deletion Lucify/app/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ export const toggleReview = (value) => ({ type: TOGGLE_REVIEW, payload: value })
export const toggleSearchReview = (value) => ({ type: TOGGLE_SEARCH_REVIEW, payload: value });
export const toggleModal = () => ({ type: TOGGLE_MODAL, payload: {} });
export const setReviewWeights = (weights) => ({ type: SET_WEIGHTS, payload: weights });
export const setBusiness = (business) => ({ type: SET_BUSINESS, payload: business })
export const setBusiness = (business) => ({ type: SET_BUSINESS, payload: business });
32 changes: 3 additions & 29 deletions Lucify/app/components/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,17 @@ const VisibilityContainer = posed.div({
transition: {
opacity: { ease: 'easeOut', duration: 300 },
},
applyAtStart: { display: 'block' },
applyAtStart: { display: 'block', height: '100%' },
},
hidden: {
height: 0,
opacity: 0,
transition: { ease: 'easeOut', duration: 500 },
applyAtEnd: {
display: 'none',
height: '100%',
},
}
});

const ReviewInputContainer = posed.div({
move: {
delay: 400,
transition: { duration: 500 },
},
visible: {
opacity: 1,
transition: {
opacity: { ease: 'easeOut', duration: 300 },
},
applyAtStart: { display: 'block' },
},
hidden: {
height: 0,
opacity: 0,
transition: { ease: 'easeOut', duration: 500 },
applyAtEnd: {
display: 'none',
height: '100%',
},
}
});

const ResultsContainer = posed.div({
visible: {
Expand Down Expand Up @@ -135,7 +111,7 @@ class Main extends React.Component {
})
.then((res) => res.json())
.then((response) => {
setReviewWeights({ weights: [response] });
setReviewWeights([response]);
toggleReview(true);
});
}
Expand Down Expand Up @@ -172,14 +148,12 @@ class Main extends React.Component {
<Search />
</VisibilityContainer>
</VisibilityContainer>
<ReviewInputContainer pose={showReviewResults ? 'move' : null}>
{this.getGhostField()}
</ReviewInputContainer>
<ResultsContainer pose={showResults ? 'visible' : 'hidden'}>
{showResults &&
<Results />
}
</ResultsContainer>
{this.getGhostField()}
</div>
);
}
Expand Down
168 changes: 120 additions & 48 deletions Lucify/app/components/results.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,69 @@ import cx from 'classnames';
import { forEach } from 'lodash';
import { connect } from 'react-redux';

const PALETTE = [
'#e0312f',
'#e65b22',
'#ed9217',
'#e2a822',
'#000000',
'#b0c323',
'#75bb25',
'#47d131',
'#46bc48'
];

class Results extends Component {
getWordColour(confidence) {
const fixedConfidence = confidence.toFixed(2);
switch (true) {
case (fixedConfidence > 0.75):
return PALETTE[0];
case (fixedConfidence > 0.5 && fixedConfidence < 0.75):
return PALETTE[1];
case (fixedConfidence > 0.25 && fixedConfidence < 0.5):
return PALETTE[2];
case (fixedConfidence > 0 && fixedConfidence < 0.25):
return PALETTE[3];
case (fixedConfidence === 0):
return PALETTE[4];
case (fixedConfidence < 0 && fixedConfidence > -0.25):
return PALETTE[5];
case (fixedConfidence < -0.25 && fixedConfidence > -0.5):
return PALETTE[6];
case (fixedConfidence < -0.5 && fixedConfidence > -0.75):
return PALETTE[7];
case (fixedConfidence < -0.75):
return PALETTE[8];
default:
return PALETTE[4];
}
}

calculateAccuracy(confidence) {
let positiveConfidence = Math.abs(confidence.toFixed(2));
if (positiveConfidence > 1) {
positiveConfidence = 1;
}
return positiveConfidence * 100;
}

compareConfidence(first, second) {
const firstAccuracy = this.calculateAccuracy(first.confidence);
const secondAccuracy = this.calculateAccuracy(second.confidence);
if (firstAccuracy < secondAccuracy) {
return 1;
} if (firstAccuracy > secondAccuracy) {
return -1;
}
return 0;
}

renderAccuracy(accuracy) {
const accuracyClasses = cx({
'is-size-1': true,
pr10: true,
pl10: true,
'is-2': true,
'has-text-warning': accuracy >= 50 && accuracy < 70,
'has-text-danger': accuracy < 50,
'has-text-success': accuracy > 70
Expand All @@ -19,60 +77,68 @@ class Results extends Component {
);
}

renderVerdict(verdict) {
renderVerdict(verdict, index) {
const verdictClasses = cx({
'is-size-1': true,
pl10: true,
'has-text-danger': verdict === 'Deceptive',
'has-text-success': verdict === 'Truthful',
'has-text-success': verdict === 'Genuine',
});

const iconClasses = cx({
fas: true,
mr20: true,
'has-text-danger': verdict === 'Deceptive',
'has-text-success': verdict === 'Genuine',
'fa-times-circle': verdict === 'Deceptive',
'fa-check-circle': verdict === 'Truthful',
'fa-check-circle': verdict === 'Genuine',
});

return (
<p className={verdictClasses}>
<p className="card-header-title is-2">
Review {index + 1}:
<span className={verdictClasses}> {verdict}</span>
<span className="pl10"><i className={iconClasses}></i></span>
<span>
{verdict}
</span>
</p>
);
}

renderReview(featureWeights, review) {
const splitReview = review.split(' ');
const reviewText = [];
forEach(splitReview, (value, index) => {
const wordValue = featureWeights[value];
const color = this.getWordColour(wordValue);
reviewText.push(
<span key={`${value}-${index}`} style={{ color: color }}>{value}</span>
);
reviewText.push(<span key={`${value}-${index}-2`}> </span>);
});
return (
reviewText
);
}

render() {
const { weights, business } = this.props;
const resultsArray = [];
weights.sort((first, second) => this.compareConfidence(first, second));
forEach(weights, (weight, index) => {
const accuracy = weight.classProbs[0][0].toFixed(2) * 100;
const verdict = weight.result;
const { confidence, result, feature_weights, review} = weight;
resultsArray.push(
<div className="is-fluid pt20" key={`result-${index}`}>
<div className="tile is-ancestor has-text-centered">
<div className="tile is-vertical">
<div className="tile is-parent is is-vertical">
<div className="tile is-parent">
<div className="tile is-child">
<div className="card">
<div className="card-header">
<p className="card-header-title is-2">Verdict</p>
</div>
<div className="card-content">
{this.renderVerdict(verdict)}
</div>
<div className="tile is-ancestor">
<div className="tile is-parent">
<div className="tile is-child">
<div className="card">
<div className="card-header">
{this.renderVerdict(result, index)}
<div className="card-header-title is-3">
Confidence:
{this.renderAccuracy(this.calculateAccuracy(confidence))}
</div>
</div>
<div className="tile is-child">
<div className="card">
<div className="card-header">
<p className="card-header-title is-2">Confidence Score</p>
</div>
<div className="card-content">
{this.renderAccuracy(accuracy)}
</div>
</div>
<div className="card-content">
{this.renderReview(feature_weights, review)}
</div>
</div>
</div>
Expand All @@ -85,25 +151,31 @@ class Results extends Component {
return (
<div>
{business &&
<div className="box tile">
<div className="tile is-parent is-2">
<figure className="image is-64x64 tile is-child">
<img className="is-rounded" src={business.image_url} />
</figure>
</div>
<div className="tile is-parent is-vertical">
<div className="tile is-child">
<a href={business.url} target="_blank" rel="noopener noreferrer" className="title">{business.name}</a>
</div>
<div className="tile is-child">
<div>Rating: {business.rating}</div>
<div className="card mb10">
<div className="card-content">
<div className="media">
<div className="media-left">
<figure className="image is-64x64">
<img src={business.image_url} />
</figure>
</div>
<div className="media-content columns">
<div className="column is-4">
<a href={business.url} target="_blank" rel="noopener noreferrer" className="title is-4">{business.name}</a>
<div className="has-text-success is-size-4">{business.price}</div>
</div>
<div className="column is-2">Rating: {business.rating}/5</div>
<div className="column is-3">
<div>Address:</div>
<div>{business.location.address1}</div>
<div>{business.location.display_address[1]}</div>
</div>
</div>
</div>
</div>
</div>
}
<div>
{resultsArray}
</div>
{resultsArray}
</div>
);
}
Expand All @@ -112,7 +184,7 @@ class Results extends Component {

const mapStateToProps = (state) => {
return {
weights: state.weights.weights,
weights: state.weights,
business: state.business
};
};
Expand Down
Loading

0 comments on commit a4437da

Please sign in to comment.