Created
November 20, 2017 23:34
-
-
Save kylemcdonald/36fc527b18a41c06024863fd6c6f2773 to your computer and use it in GitHub Desktop.
Export visualizations for comparing UMAP to t-SNE.
This file contains hidden or 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
| #include "ofMain.h" | |
| template <class T> | |
| vector<T> loadEmbedding(string filename) { | |
| vector<T> embedding; | |
| ofBuffer embeddingBuffer = ofBufferFromFile(filename); | |
| for(auto& line : embeddingBuffer.getLines()) { | |
| if(line.size()) { | |
| T x; | |
| stringstream(line) >> x; | |
| embedding.emplace_back(x); | |
| } | |
| } | |
| return embedding; | |
| } | |
| void flip(vector<ofVec2f>& v, bool flip_x=false, bool flip_y=false) { | |
| for(ofVec2f& x : v) { | |
| if(flip_x) { | |
| x.x = 1 - x.x; | |
| } | |
| if(flip_y) { | |
| x.y = 1 - x.y; | |
| } | |
| } | |
| } | |
| float orientation_difference(vector<ofVec2f>& a, vector<ofVec2f>& b, ofVec2f pivot=ofVec2f(0.5, 0.5)) { | |
| float sum = 0; | |
| int n = a.size(); | |
| for(int i = 0; i < n; i++) { | |
| float diff = (a[i] - pivot).angle(b[i] - pivot); | |
| sum += diff; | |
| } | |
| return sum / n; | |
| } | |
| void rotate(vector<ofVec2f>& v, float angle, ofVec2f pivot=ofVec2f(0.5, 0.5)) { | |
| for(ofVec2f& x : v) { | |
| x.rotate(angle, pivot); | |
| } | |
| } | |
| class ofApp : public ofBaseApp { | |
| public: | |
| vector<float> colors; | |
| vector<ofVec2f> umap, tsne; | |
| vector<ofImage> images; | |
| ofTrueTypeFont font; | |
| void setup() { | |
| ofSetFrameRate(60); | |
| ofBackground(0); | |
| ofSetColor(0); | |
| glPointSize(2); | |
| ofEnableSmoothing(); | |
| ofEnableAlphaBlending(); | |
| font.load("Andale Mono.ttf", 32); | |
| // tsne = loadEmbedding<ofVec2f>("tsne_embedding_subset.tsv"); | |
| // umap = loadEmbedding<ofVec2f>("umap_embedding_subset.tsv"); | |
| // for(int i = 0; i < umap.size(); i++) { | |
| // images.emplace_back("zeros/" + ofToString(i) + ".png"); | |
| // } | |
| colors = loadEmbedding<float>("y.tsv"); | |
| tsne = loadEmbedding<ofVec2f>("tsne_embedding.tsv"); | |
| umap = loadEmbedding<ofVec2f>("umap_embedding.tsv"); | |
| // flip(tsne, false, true); | |
| // float angle = orientation_difference(tsne, umap); | |
| // rotate(tsne, angle); | |
| } | |
| void update() { | |
| } | |
| void draw() { | |
| float pad = 0.1; | |
| float t = ofMap(sin(ofGetFrameNum() * TWO_PI / 128), -1, +1, 0, 1); | |
| // float t = ofMap(sin(ofGetElapsedTimef()), -1, +1, 0, 1); | |
| ofMesh mesh; | |
| vector<ofVec2f> points; | |
| mesh.setMode(OF_PRIMITIVE_POINTS); | |
| int n = tsne.size(); | |
| for(int i = 0; i < n; i++) { | |
| ofVec2f x = tsne[i].getInterpolated(umap[i], t); | |
| mesh.addVertex(ofVec3f(x)); | |
| if(i < colors.size()) { | |
| mesh.addColor(ofFloatColor::fromHsb(colors[i], 1, 1, .50)); | |
| } | |
| points.push_back(x); | |
| // x -= 0.5; | |
| // x *= (1-pad) * ofGetWidth(); | |
| // x += ofGetWidth()/2; | |
| // images[i].draw(x); | |
| } | |
| string text = t < 0.5 ? "t-SNE" : "UMAP"; | |
| ofSetColor(255); | |
| font.drawString(text, 20, 60); | |
| ofTranslate(ofGetWidth()/2, ofGetHeight()/2); | |
| ofScale(ofGetWidth()*(1-pad), ofGetHeight()*(1-pad)); | |
| ofTranslate(-0.5, -0.5); | |
| mesh.draw(); | |
| if(ofGetFrameNum() < 128) { | |
| ofSaveScreen("screenshot-" + ofToString(ofGetFrameNum(), 4, '0') + ".png"); | |
| } | |
| } | |
| }; | |
| int main() { | |
| ofSetupOpenGL(1024, 1024, OF_WINDOW); | |
| ofRunApp(new ofApp()); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment