Browse files

Transferred URLs to .name. Slight CSS tweaks for comment counts. New …

  • Loading branch information...
Mark Reid
Mark Reid committed Jan 20, 2009
1 parent c18f97c commit c1c7d01bcde70f5b9116408a88880f3aa69078ba
@@ -25,6 +25,8 @@
DB_USER = 'root'
DB_NAME = 'inductio'
# Gets the first forum key associated with USER_KEY
def forum_key
forum_list = get('get_forum_list', :user_api_key => USER_KEY)
@@ -53,37 +55,38 @@ def convert(row)
-def clean(comment)
- comment.gsub!(/<\/?p>/,'')
- comment
+# Remove extraneous paragraph separators. Disqus interprets double
+# newline as paragraphs
+def clean(comment)
+ comment.gsub(/<\/?p>/,'')
+# Compute the URL for the given comment based on the DB entry
def url(row)
date_path = row[:comment_date_gmt].strftime("%Y/%m/%d")
- "{row[:post_name]}.html"
+ "#{TARGET_URL}#{row[:post_name]}.html"
+# Get the Disqus thread ID for the comment in the DB row
def thread(row)
- ident_str = "test-#{row[:post_name]}"
+ ident_str = "#{row[:post_name]}"
data = {
:forum_api_key => FORUM_KEY,
:title => row[:post_title],
:identifier => ident_str
- puts "Getting thread #{ident_str}..."
response = JSON.parse( DISQUS['thread_by_identifier'].post(data) )
+ unless response['succeeded']
+ raise "Bad response to get thread ID for #{ident_str}"
+ end
- # puts response.to_yaml
- # puts "--- (end thread response)"
- raise "Bad response to get thread ID for #{ident_str}" unless response['succeeded']
- puts "Thread [#{ident_str}] has title '#{response['message']['thread']['title']}'"
+ puts "Set thread [#{ident_str}] title to '#{response['message']['thread']['title']}'"
+# Set the URL of the Disqus thread to the given value
def update(thread_id, url)
data = {
:forum_api_key => FORUM_KEY,
@@ -95,9 +98,11 @@ def update(thread_id, url)
response = JSON.parse( DISQUS['update_thread'].post(data) )
-# Converts and sends a comment from the DB to Disqus with the given thread ID
@unconverted = []
@threads = {}
+# Converts and sends a comment from the DB to Disqus with the given thread ID
+# Failed conversions are stored in @unconverted and the thread_id to URL mapping
+# in @threads is updated
def post(row, thread_id)
data = convert(row)
data[:forum_api_key] = FORUM_KEY
@@ -111,28 +116,36 @@ def post(row, thread_id)
@threads[thread_id] = url(row)
puts "\tWARNING: Could not post comment by #{data[:author_name]} on #{data[:created_at]}"
+ puts data.to_yaml + "\n---"
@unconverted << data
# Processing begins here...
-DB = Sequel.mysql(DB_NAME, :user=>DB_USER, :password=>DB_PASS, :host=>'localhost')
+DB = Sequel.mysql(DB_NAME,
+ :user=>DB_USER, :password=>DB_PASS, :host=>'localhost', :encoding => 'utf8'
FORUM_KEY = forum_key
-LIMIT = "limit 10"
-QUERY = "select * from wp_comments, wp_posts where wp_comments.comment_post_ID = wp_posts.ID and comment_type != 'pingback' #{LIMIT}"
+QUERY = "select * from wp_comments, wp_posts where wp_comments.comment_post_ID = wp_posts.ID and comment_type != 'pingback'"
DB[QUERY].each do |row|
puts "Processing #{row[:comment_type]} comment #{row[:comment_ID]}..."
thread_id = thread(row)
post(row, thread_id)
-puts "Number of failures: #{@unconverted.length}"
+# Update all of the threads with the correct URL
@threads.each do |tid,url|
+# Print unconverted data to STDOUT as YAML
+puts "Number of failures: #{@unconverted.length}"
+puts "\n\n***UNCOVERTED POSTS***"
+@unconverted.each do |data|
+ puts data.to_yaml
+ puts "***"
@@ -0,0 +1,78 @@
+require 'rubygems'
+require 'rest_client'
+require 'json'
+10211725 => '',
+10211748 => '',
+10211737 => '',
+10211738 => '',
+10211739 => '',
+10211728 => '',
+10211784 => '',
+10211740 => '',
+10211730 => '',
+10211753 => '',
+10211742 => '',
+10211720 => '',
+10211710 => '',
+10211755 => '',
+10211733 => '',
+10211711 => '',
+10211713 => '',
+# Gets the first forum key associated with USER_KEY
+def forum_key
+ forum_list = get('get_forum_list', :user_api_key => USER_KEY)
+ forum_id = forum_list[0]['id']
+ get('get_forum_api_key', :user_api_key => USER_KEY, :forum_id => forum_id)
+# Encapsulates request, JSON parsing and error checking a REST call to Disqus
+def get(command, args)
+ path = command + '?' + {|k,v| "#{k}=#{v}"}.join('&')
+ response = JSON.parse( DISQUS[path].get )
+ raise "Bad response to #{path}" unless response['succeeded']
+ response['message']
+def threads
+ thread_list = get('get_thread_list', :forum_api_key => FORUM_KEY)
+# Set the URL of the Disqus thread to the given value
+def update(thread_id, url)
+ data = {
+ :forum_api_key => FORUM_KEY,
+ :thread_id => thread_id,
+ :url => url
+ }
+ puts "Updating thread #{thread_id} with URL = #{url}"
+ response = JSON.parse( DISQUS['update_thread'].post(data) )
+FORUM_KEY = forum_key
+# Set the new URLs
+# threads.each do |t|
+# url = THREADS[t['id'].to_i]
+# next if url.nil?
+# update(t['id'], url)
+# puts "Set thread #{t['id']} to #{url}"
+# end
+# Check everything worked
+threads.each do |t|
+ url = THREADS[t['id'].to_i]
+ next if url.nil?
+ puts "Thread #{t['id']} has #{url}"
@@ -96,6 +96,7 @@ hr {
.left.inset { margin-left: 0 !important; }
.list .title { font-weight: bold; }
+.comments { font-size: smaller; display: block; float: right; color: silver;}
.excerpt { color: black; }
blockquote {
@@ -0,0 +1,37 @@
+layout: post
+title: Information, Divergence and Risk for Binary Experiments
+excerpt: A summary of a recent paper Bob and I posted to arXiv.
+location: Canberra, Australia
+wordpress_id: 175
+[Bob Williamson][bob] and I have finished a [report][] outlining what we have been looking at for the last year or so and uploaded it to the arXiv. Weighing in at 89 pages, it covers a lot of ground in an attempt to unify a number of different classes of measures for problems that can be expressed as binary experiments. That is, where instances are drawn from two distributions. This include binary classification, class probability estimation, and hypothesis testing.
+We show that many of the usual measures of difficultly for these problems — divergence, information and Bayes risk — are very closely related. We also look at ways in which members of each class of measure can be expressed in terms of "primitive" members of those classes. In particular, Fisher-consistent losses (also known as proper scoring rules) can be written as weighted sums of cost-sensitive loss while all f-divergences can be written as weighted sums of something akin to cost-sensitive variational divergence. These "Choquet representations" make it easy to derive Pinsker-like bounds for arbitrary f-divergences (not just KL divergence) as well as results similar to those of Bartlett et al in their "[Convexity, classification and Risk Bounds][bartlett]".
+It should be made clear that many of these results are not new. However, what I like about our approach is that almost all of the results in the paper stem from a two observations about convex functions: they are invariant under the Legendre-Fenchel bidual, and they have a second-order integral Taylor expansion with non-negative weights.
+If any of this sounds interesting, you should grab the full paper from the [arXiv][report]. Here's the abstract:
+> We unify f-divergences, Bregman divergences, surrogate loss bounds (regret bounds),
+> proper scoring rules, matching losses, cost curves, ROC-curves and information. We
+> do this by systematically studying integral and variational representations of these
+> objects and in so doing identify their primitives which all are related to cost-sensitive
+> binary classification. As well as clarifying relationships between generative and
+> discriminative views of learning, the new machinery leads to tight and more general
+> surrogate loss bounds and generalised Pinsker inequalities relating f-divergences to
+> variational divergence. The new viewpoint illuminates existing algorithms: it provides a
+> new derivation of Support Vector Machines in terms of divergences and relates
+> Maximum Mean Discrepancy to Fisher Linear Discriminants. It also suggests new
+> techniques for estimating f-divergences.
+Now that we have a good understanding of binary experiments the aim is to build on these results and extend this type of work to other forms of machine learning problems. High on the list are multi-category classification, ranking and regression problems.
+Questions, criticism, suggestions and pointers to related work we may have missed are all welcome.
@@ -0,0 +1,78 @@
+layout: post
+title: ML and Stats People on Twitter
+excerpt: Wherein I compile a list of interesting people who use Twitter to discuss machine learning and statistics.
+location: Canberra, Australia
+wordpress_id: 171
+I started using the social, "micro-blogging" service [Twitter][] in February this year simply because I had been seeing so much commentary about it — both good and bad. Since then, I've posted [800+ updates][me], amassed over 100 [followers][] and [follow][] nearly that many myself.
+What has surprised me about Twitter is how many people I have found on there who are active, or at least interested, in machine learning and statistics. The day-to-day discussions, questions, advice and pointers I've got via Twitter have been illuminating and fun.
+In an effort to get to know some of these people a bit better I followed the links they provided in their respective profiles to see what they had to say about themselves. The descriptions below are based only on those links as I don't find Google-stalking very friendly.
+So, in no particular order, here they are:
+* [Tim Danford](
+A computer science [Ph.D. student at MIT](
+* [Mark James Adams](
+"[I am a student of quantitative genetics and a temperamental psychologist]("
+* <a href="" rel="nofollow">Dave Warde-Farley</a>
+[Computer science Masters student at Toronto]( working in machine learning
+* [Amir massoud Farahmand](
+Ph.D. student looking at manifold learning (amongst other things) at the [University of Alberta]( Runs the blog [thesilog](
+* [Markus Weimer](
+Graduate student working on "[applications of machine learning to eLearning](". Also runs a [blog](
+* [Ryan Rosario](
+Statistics and computer science graduate student.
+* [A.M. Santos](
+Maths and statistics graduate student.
+* [Neal Richter](
+Neal Richter - Runs the blog [aicoder](
+* [Brendan O'Connor](
+[Research assistant]( in NLP at Stanford and consultant at [Dolores Labs](
+* [Daniel Tunkelang](
+Chief scientist at the information retrieval company Endeca and owner of the blog [The Noisy Channel](
+* [Jason Adams](
+Computational linguist work on sentiment analysis. Runs the blog [The Mendicant Bug](
+* [Mikio Braun](
+Post-doc at Technische Universität Berlin and a machine learning blogger at [Marginally Interesting](
+* [Daniel Lemire](
+Professor of computer science at the University of Quebec at Montreal and [blogger](
+* [Jason H. Moore](
+Professor of Genetics, Director of Bioinformatics at Dartmouth Medical School. Works on the [Multi-factor Dimensionality Reduction]( software MDR and blogs at [Epistasis](
+* [Pete Skomoroch](
+Director of analytics at Juice Analytics and [Data Wrangling]( blogger.
+* [Alex Smola](
+Principal Researcher at Yahoo! Research and ex-colleague of mine at [NICTA]( and the [ANU]( a.k.a. "Mr. Kernel"
+If you are not on this list but think you should be, leave a comment below and I'll update this list. Conversely, if I've put you on this list and you don't wish to be associated with these sorts of people, leave a comment or send me an email and I'll remove you.
+Of course, feel free to follow [me][] if you'd like to keep up with what I'm doing.
Oops, something went wrong.

0 comments on commit c1c7d01

Please sign in to comment.