AI and the Souls of Black Folk

The impact of AI on communities of color — particularly through job displacement and policing — is now undeniable. Given that HBCUs have historically been on the forefront of technology education for the Black community, I am proposing to build a list of current activities (courses, research, seminars, clubs, etc.) at the HBCUs relevant to AI and its wider implications. If you’d like to contribute to the list, I’ll eagerly accept your input! To understand some of my motivations, keep reading.

We’ve now reached the point where the impact of Artificial Intelligence (AI) upon everyday life is undeniable. Everyone takes Siri for granted, your local Walmart can hook you up with a drone that does object recognition, and the introduction of self-driving cars now seems inevitable.

The title of my post is inspired both by W.E.B. Du Bois’s classic The Souls of Black Folk — a collection of essays on the state of African Americans at the start of the 20th century — and by Tracy Kidder’s The Soul of a New Machine which chronicles the development of a computer architecture at the end of the 20th century. I think that at the start of the 21st century, a critical look at how African Americans are impacted by immense technological change is needed. The title tries to capture my central question:

What is the impact of AI and related technologies on the lives of Black folk, and how can we organically shape a future for these technologies that enhances opportunity rather than reifies oppression?

To be honest, I am deeply concerned about the potential AI has for disruptive and devastating impact on communities of color. The Obama administration released a sobering assessment of the  economic impact of AI — it forecasts that changes in the transportation sector alone (trucking and delivery) will mean the elimination of occupations which Black and Brown folk have relied upon for entry into the middle class. Those findings are likely to generalize to other occupations. The prevalence of predictive policing and algorithmic sentencing raise serious concerns about equality and self-determination — especially when mass incarceration and other racial disparities in criminal justice are taken into account.

In theory, a modern democracy should allow impacted communities to raise concerns about a technology and then foster the deliberative processes necessary to fairly address those concerns. In theory, the open source movement provides a model through which communities can identify and develop technologies that serve their particular needs.

You might respond that “technology is colorblind, science is colorblind, it shouldn’t matter whether there are any Black folk involved at all in the development of and policy making around AI technology“. I think in this case particularly, it matters a great deal. AI, looking back over its history, is itself an endeavor that grapples with the question of what it means to be human — it is an endeavor that demands broad societal input. 

Aside from President Obama’s initiative, I see very little presence of the disenfranchised in discussions on the future course of AI. For example, OpenAI is a research institute of sorts formed with the express purpose of “discovering and enacting the path to safe artificial general intelligence“. Despite lofty claims OpenAI seems to have the traditional Silicon Valley underrepresentation.

So all that said, what is the simplest concrete contribution I can make?

I have spent most of my career in AI. I grew up in Atlanta, attended Morehouse College and Georgia Tech through the Atlanta University Center’s Dual Degree Program, and went on later to complete a doctorate in computer science at the University of Chicago focusing on robot planning and learning. Along the way I studied and worked with other Black people doing advanced computing, witnessed Black people found successful technology startups and saw Black women and men lead successful academic careers in these fields. On the one hand, the diversity (exclusion?) figures we see from Facebook and Google seem at odds with  that experience. On the other hand, it jibes with the experience of being “the one and only” in many places I’ve worked or studied at. I wanted to begin to quantify and understand the dimensions and particulars of exclusion — things just don’t seem to add up, so perhaps we are looking in the wrong places and asking the wrong questions when we conclude there are no Black folk doing AI?

The Historically Black Colleges and Universities (HBCUs) provided the fertile intellectual soil in which Du Bois’s ideas sprouted and grew. So I thought my first concrete step would be to take inspiration from Tracy Chou’s Women in Software Engineering and put together a set of Google spreadsheets that document how HBCUs are looking at AI.

I created the spreadsheet AI at HBCUs. Please give it a look. Right now it is an aspirational document in that it tries to gather up any kind of activity at the HBCUs related to AI, Machine Learning, or Data Science. Hopefully it can be the basis of other kinds of summary statistics, update posts,  or active development efforts.

I’ve split the document into a number of sheets:

Sheet Name

Description

HBCUS

Name and address information for US HBCUs based on information obtained from IPEDS

Course

Information on AI related courses taught at the institution. Any department.

Grants

Information on grants received by the HBCU for AI related work

Publications

Publications on AI related topics.

Clubs

Student related clubs. For example a robotics club, drone club, a group formed for Kaggle competitions, etc.

Workshops and Seminars

Has the institution hosted any seminars or workshops? Links to videos would be great.

Outreach

Any Saturday events for grade schoolers? Teach-ins for community organizers?

Graduate Placements

Any numbers on the graduates who’ve gone on to careers, graduate school or internships in AI related fields.

Here’s how I think this could work. If you are a  faculty or a student at a HBCU, you can for the time being send an email to me charles.cearl@gmail.com with information on courses, seminars, research, clubs, outreach programs or other related activity at your institution. I’ll manually post your information to the relevant sheet. If there’s enough interest, I can just set this up to allow direct update (through pull requests or direct editing of the relevant sheet). I’m open to suggestions on formatting, information gathering, and overall focus.

Let’s get the discussion started!

Scheme in 33 Miniatures

This weekend I was trying to wake my old brain up by looking and the clever and mind-bending problems from my graduate school. I have really gotten excited about Madhur Tulsi‘s Mathematical Toolkit class — as a “data scientist”/”machine learning engineer” (I sometimes wonder what these designations mean — heck I just am grateful to have been able to work on A.I. with all its challenges and contradictions for a couple of decades) I find myself treasuring the notes and exercises.

One gem that I found is the text Thirty-three Miniatures: Mathematical and Algorithmic Applications of Linear Algebra by Jiřì Matoušek. This is full of memorable tricks and insights that leverage linear algebra. While the text is mostly about proofs, I used some of the algorithms presented discussions do some Lisp programming this weekend.

I started off with the first two miniatures on Fibonacci numbers — the first presenting a fast method to get the nth Fibonacci number and the second which is probably not so fast is yet elegant in that it presents a function to compute Fibonacci numbers.

So first, I wanted to re-awaken my Lisp programming brain. Racket is definitely one of the more innovative Lisp languages to have emerged over the last 10 years. You can think of Racket as a package that provides a collection of Lisp-languages, among them standard Scheme — a paired down Lisp dialect.

The first implementation achieves O(logn) running time by using exponentiation by squaring. This is achieved by first realizing that the Fibonacci recurrence can be written in terms of a matrix polynomial \begin{pmatrix} F_(n+1)\\ F_(n)\end{pmatrix} = M^n \begin{pmatrix} 1\\ 0\end{pmatrix} where M = \begin{pmatrix} 1 & 1\\ 1 & 0\end{pmatrix}. I hadn’t known this but n is a power of 2 we can compute the M^n by repeatedly squaring M and then the case where n is odd is taken care of by a multiply. I’m guessing that the core exponentiation routine would use this (or a faster method) anyway, but still interesting to consider.

So first to see if a quick exponentiation by squaring does against the method provided in the racket math/matrix package. Here’s my quick recursive method, based on the tail recursive method in the wikipedia article

;;identity
(define one-matrix (matrix [[1 0] [0 1]]))
;;recursive exponentiation by squaring
(define (exp-by-squaring x n)
   (letrec
    (
     [exp-by-squaring-aux
       (lambda (y x n)
         (cond
          [(= n 0) y]
          [(= n 1) (matrix* y x)]
          [(= (modulo n 2) 0)
            (exp-by-squaring-aux y (matrix* x x) (/ n 2))]
          [else
            (exp-by-squaring-aux
             (matrix* y x) (matrix* x x) (/ (- n 1) 2))]))])
    (exp-by-squaring-aux one-matrix x n)))

And here is a quick running time analysis

> (time (dotimes (x 1000) (exp-by-squaring (matrix [[1 1 ] [1 0]]) 100)))
cpu time: 793 real time: 802 gc time: 175
> (time (dotimes (x 1000) (matrix-expt (matrix [[1 1 ] [1 0]]) 100)))
cpu time: 143 real time: 144 gc time: 36
>

Looks like I’m better off with the library — although curious to know what the library implementation is.

So sticking with the matrix-expt library function:

;;;-- Miniature 1: Fibonacci Numbers, Quickly
(define one-zero-matrix (matrix [[1 0]]))

(define fib-matrix (matrix [[1 1 ] [1 0]]))

(define (fast-fib n)
 ;;; Fast method of computing nth fibonnaci number
 (let* (
         [m-expt (matrix-expt fib-matrix n)]
         [idx0 0]
         [idx1 1]
         [prod (matrix* one-zero-matrix m-expt )]
        )
    (matrix-ref prod idx0 idx1 )))

Now here’s an old-school tail recursive implementation

;;; Old school fib
(define (os-fib n)
 (letrec ([os-fib-helper 
            (lambda (n a b)
             (cond
              [(= n 0) b]
              [else
                (os-fib-helper (- n 1) b (+ a b) )]))])
         (cond
           [(= n 0) 0]
           [(= n 1) 1]
           [else
             (os-fib-helper (- n 2) 1 1)])))

Now let’s look at how they compare.

> (time (dotimes (x 10000) (fast-fib 100)))
cpu time: 2554 real time: 2612 gc time: 617
> (time (dotimes (x 10000) (os-fib 100)))
cpu time: 41 real time: 41 gc time: 11

Wow. Maybe we’ll have to go to type checked racket to see any gains there!

Typed racket claims to get more of a boost in performance by using type hints. Here is the typed version of the fast Fibonacci

;;; -- Miniature 1: Fibonacci Numbers, Quickly (with type hints)
(: one-zero-matrix (Matrix Integer))
(define one-zero-matrix (matrix [[1 0]]))

(: fib-matrix (Matrix Integer))
(define fib-matrix (matrix [[1 1 ] [1 0]]))

(: fast-fib (-> Integer Integer))
(define (fast-fib n)
 ;;; Fast method of computing nth fibonnaci number
 (let* 
  (
   [m-expt (matrix-expt fib-matrix n)]
   [idx0 : Integer 0]
   [idx1 : Integer 1]
   [prod : (Matrix Any) (matrix* one-zero-matrix m-expt )]
  )
  (cast (matrix-ref prod idx0 idx1 ) Integer)))

;;Hacky runner to allow my bootleg benchmark
(: run-fast-fib-100 (-> Integer Integer))
(define (run-fast-fib-100 n)
  (dotimes (x n)
   (fast-fib 100))
 n)
> (time (run-fast-fib-100 10000))
cpu time: 689 real time: 728 gc time: 251
- : Integer
10000
> (time (run-fast-fib-100 10000))
cpu time: 672 real time: 733 gc time: 244
- : Integer
10000
> (time (run-fast-fib-100 10000))
cpu time: 704 real time: 750 gc time: 267
- : Integer
10000
> (time (dotimes (x 10000) (os-fib 100)))
cpu time: 28 real time: 28 gc time: 0
> (time (dotimes (x 10000) (os-fib 100)))
cpu time: 31 real time: 30 gc time: 0
> (time (dotimes (x 10000) (os-fib 100)))
cpu time: 35 real time: 35 gc time: 0
>

About an order of magnitude better, but still order of magnitude worse than the iterative version though. Better off sticking with the simple iteration.

Now in the second miniature, Matoušek derives a numeric expression for the nth Fibonacci number by solving a system of linear equations that follow from the recurrence. This is F_n = 1/\sqrt{5} \left[ \right( (1 + \sqrt{5})/2 \left) ^n - \right( (1 - \sqrt{5})/2 \left) ^n \right]

;;; -- Miniature 2: Fibonacci Numbers, the Formula(: root-five Real) 
(define root-five (sqrt 5.0)) 

(define inv-root-five (/ 1.0 root-five)) 

(define first-tau-root (/ (+ 1.0 root-five) 2.0)) 

(define second-tau-root (/ (- 1.0 root-five) 2.0)) 

(define (fib-root n) 
 ;;; Not so fast but fun ?
 (exact-round 
    (* inv-root-five 
     (- (expt first-tau-root n) (expt second-tau-root n))))

How does compare against an “old school” iterative version?

> (time (dotimes (x 10000) (fib-root 100)))
cpu time: 3 real time: 4 gc time: 0
> (time (dotimes (x 10000) (os-fib 100)))
cpu time: 27 real time: 28 gc time: 0

Well, that seems to best it. At least until we get further out in the sequence, where overflow gets to be an issue

> (time (dotimes (x 10000) (fib-root 1200)))
cpu time: 4 real time: 4 gc time: 0
> (time (dotimes (x 10000) (os-fib 1200)))
cpu time: 1271 real time: 1419 gc time: 293
> > (time (dotimes (x 10000) (fib-root 2000)))
. . exact-round: contract violation
 expected: rational?
 given: +inf.0
> (time (dotimes (x 10000) (os-fib 2000)))
cpu time: 2619 real time: 2893 gc time: 725

So we’ve got constant time with the analytic solution, we might loose the better performance once we get better precision. Interesting. I’ll hold it there for now and contemplate. It’s been a nice Scheme appetizer — a feel my inner Scheme brain re-awakening.