1. Don't write anything down.
2. Your brain will automagically forget all the todos that aren't important.
Not for everyone of course, but for me it works far better than any of my previous methods.
1,374 karma · joined April 12, 2017
Working at https://tyba.ai
Building https://yakread.com and https://biffweb.com
email: hello@obryant.dev
1. Don't write anything down.
2. Your brain will automagically forget all the todos that aren't important.
Not for everyone of course, but for me it works far better than any of my previous methods.
If they're using collaborative filtering, there probably isn't a simple explanation. Basically, you feed in a list of "<user id>, <book id>, <rating>" and the algorithm generates a feature vector for each book and each user. So the reason some book gets recommended is because... the dot product of that book's vector with your vector was high. You can do this easily with off-the-shelf libraries, like Surprise[1] (I'm using that lib in my startup[2]).
At least this is what happens in matrix factorization methods. Recommendations from k-nearest neighbor methods can be explained more easily, but knn doesn't scale as well.
This is a minor drawback of matrix factorization--people have been shown to trust recommendations more if they understand how the recommendations were generated. Twitter recently published a super interesting paper[3] about how they generate recommendations at scale, and as a bonus their method is explainable. They create a model that describes the communities in Twitter--groups of people who follow the same set of influencers. Users and items are represented by vectors, where each element of a vector describes to what degree a user/item fits in a certain community. When generating recommendations, you can get the user's top communities and then fetch items for those communities. If you generated a text description for each community, you could include that with each recommendation.
[1] https://github.com/NicolasHug/Surprise
[3] https://www.kdd.org/kdd2020/accepted-papers/view/simclusters...
Hey, I am working on basically this. E.g.: https://findka.com/u/jobryant (warning, takes ~10 seconds to load fully). You make a profile, add your top article/book/movie/music/etc recommendations, then you get (1) a feed of recommendations from people you follow, (2) an Explore page that gives you algorithmic recommendations (collaborative filtering, currently via an off-the-shelf SVD library).
Right now the curation is a little basic, but today I'm adding filter controls to profiles so you can see a person's recommendations for a specific content type. Eventually, I'd also like to add custom tags so you can have recommendation/awesome lists for anything.
- an atom, the contents of which describe what data you're subscribing to
- another atom, which is populated with the results of your subscriptions
- a function for handling server-sent websocket events (if your app uses any)
and it returns a function for sending websocket events to the server (which is used for sending transactions + any custom events you define).
[1] https://github.com/jacobobryant/biff/blob/98ad188924bee9121d...
2. It is inherently difficult. The closest thing like this that exists for datalog is I believe clj-3df[1]. Hence I was very excited when Materialize was launched publicly a few months ago. A version for datalog would be cool too, but SQL is good enough I think.
{[:users #uuid "some-user-uuid"] {:db/merge true
:username "foo"}}
gets converted to [[:crux.tx/put (merge (crux/entity db #uuid "some-user-uuid")
{:username "foo"})]]
There is a race condition though; if another tx updated that document after the crux/entity call but before `:username "foo"` was written, then that tx would get clobbered. I'm planning to add `:crux.tx/match` operations automatically to prevent that from happening. There was talk on #crux in Clojurians slack today of using the newly-added transaction function feature to do merges. Haven't looked into that myself.I've been doing Clojure web dev for a while but hadn't found a setup that I really liked yet. My latest approach was using Firebase + ClojureScript (for my startup[1]) which was really nice but had some significant limitations for my use case (mostly related to the ephemeral Node backend). At one point I realized that I could provide Firebase's query subscription feature using Crux[2] instead without too much effort. So I started working on Biff, and I've been using it in production for 2.5 months now. It's been a joy to use.
Also, I do think that web dev in Clojure can be a little hard to get into, due to the (appropriate) community preference for libraries over frameworks. I think there is a need for more frameworks that curate a set of libraries for you. I'd love it if Biff eventually became a sort of "Rails for Clojure" that would let anyone get up to speed quickly but would allow you to switch out the components easily as you go on.
(About the name: I named it after Biff Tannen from Back to the Future).
I was surprised to discover, long after quitting, that working full-time on your own ideas can come with it's own distraction: pressure to make money. Probably the biggest mistake I made from months 6 to 12 (startup idea #2) was being too concerned about structuring things in a way that would (hopefully) make it easier to charge money. I ended up spending a lot of time doing things that in hindsight weren't generating any value. It would've been much better to focus on doing meaningful things, whatever those may be.
I don't know the details of your situation, but that might be something to consider: if you can figure out a way to have a decent amount of time to work on whatever you want while still having an income from elsewhere, it might actually be easier to focus than if you were doing the idea full-time.
On the other hand, I am glad I quit myself. So maybe that advice is just BS.
For income: I might switch the "weeks/months" estimate to years ;). Running out of money hasn't been an issue (lots of savings from my job, my wife worked until recently, then we moved back in with my parents until the pandemic winds down). Opportunity cost of course is large, but that's fairly easy to ignore. I've learned an incredible amount during the past 18 months, so even if I can't get my startup to work, it'll have been a worthwhile investment.
I don't know if any of that is helpful. I'd be happy to chat if you like, my email's in my profile.
The algorithm uses a simple item-based neighborhood model. i.e. if you like song A, Findka looks up all the content liked by other users who liked song A and probabilistically chooses an item that was well-liked. To help the algorithm keep learning, 35% of the recommendations are purely random ("epsilon-greedy"). I describe the implementation here[0], though it's changed slightly (now I export the database every day or so and generate a model on my laptop, then I load it into memory on the server). I experimented with a machine learning-based model (a latent factor model) last week, but it seems I don't yet have enough rating data for that to be useful.
Also you're welcome! It's been really nice to actually have some users, a luxury which escaped me in previous startup attempts.
- I'll add an option for this.
- What songs were you searching for? The search feature uses Last.fm for music. They've had pretty much everything I've ever searched for, but maybe they're missing certain categories. I might investigate other/additional search APIs in the future. In the mean time, adding songs via URL is a decent option. The way the algorithm is implemented currently, it won't make a difference, and eventually I'm planning to add a cron job that'll go through the URL items and classify them as the correct content type and fetch additional metadata (with manual intervention as needed).
- I started working on this today; should be fixed tonight or tomorrow.
When you rate an item, are you sure all three items get replaced? If you rate one item, the ones below it should be moved up, and then the item on the bottom will be new. So if you rate the top item, you'll see a visual change in all items, but the other two items will still be there. Perhaps I should replace rated items in place without moving the others.
I'm actually just starting to implement features like these. If you make an account then go the the Account tab, you can enable a public profile like this[1]. So far I'm planning to add follow/subscribe, commentary (i.e. comment on items instead of just rating them), and showing users who've rated the same items as you.
[1] https://findka.com/u/f962c926-43e1-406d-825d-3d7a4880befa/
- ram usage today has gone from ~1.1GB to ~1.6GB
- DigitalOcean prices ram linearly at $5/GB (I'm currently on a $10/month droplet)
Today is a big spike obviously (the number of thumbs up/thumbs down events have gone from 3K to almost 10K today, vs going from 0 to 3K since February). But say I continue to grow ram usage at 0.5GB per week (growth hopefully won't be linear, but I'd say that's a pretty steep linear growth rate for now). That means my hosting costs would increase at a rate of $10/month which is not bad at all.
That's probably the crappiest scale estimation ever made ha ha, but I believe at least that I should have plenty of time to figure out a reliable marketing channel before I do any major re-architecting. Maybe some time I'll do a stress test on my laptop to get a better sense of how RAM usage increases with additional data.
I've been at 10s of weekly active users. I guess this should handle 100s just fine, but maybe not 1000s.
Also I hadn't heard of letterboxd or RYM. I'll check those out more when the time comes.
As far as the current music recommendations; it's nothing intelligent. Just pure collaborative filtering, i.e. it has no understanding of "this is a rock song" or "this song is from 2005" or even "this is a song". Right now, the algorithm just sees a bunch of URLs and their rating data. I am interested in making the algorithm more intelligent over time though.
Could the site not resolving be an issue with your network? It Works For Me, and I'm getting plenty of traffic right now.