How to Calculate Month over Month User Retention based on already active users (not based on user signup date)?
I am not sure I understood your requires completely, but anyway.

In Postgres I would probably do something like this: 

with per_month as (
  select to_char(a1.created_at, 'yyyy-mm') as month,
         array_agg(distinct a1.user_id) as active_users
  from user_activity a1
  where a1.created_at &gt;= timestamp '2018-12-01'
  group by month
), m2 as (
  select month, 
         active_users,
         lead(active_users) over (order by month) as january_users,
         lead(active_users,2) over (order by month) as february_users,
         lead(active_users,3) over (order by month) as march_users,
         lead(active_users,4) over (order by month) as april_users
  from per_month 
)
select month,
       cardinality(active_users) as num_users,
       (select count(*) from (select unnest(active_users) intersect select unnest(january_users)) t)  as january_retained,
       (select count(*) from (select unnest(active_users) intersect select unnest(february_users)) t)  as febrary_retained,
       (select count(*) from (select unnest(active_users) intersect select unnest(march_users)) t)  as march_retained
from m2;


The first CTE simply aggregates all users per month into an array. The second CTE then simply creates on column per month with the user of that month using a window function. 

And the final query then calculates the intersection between the users of the starting month with each of the following months by unnesting the arrays and counting the size of the intersection. 

Online example: https://rextester.com/VYNSFX1788 (note that it generates random data, so each time you run it you get a different result)