<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Demo of the ChoiceModels library
For Binary Logit and Multinomial Logit, including sampling of alternatives.
To install ChoiceModels, git clone the repository (https
Step1:  Binary Logit
Step3:  Multinomial Logit
Step5:  This is what the data looks like
Step7:  MNL with random sampling of alternatives
This example reuses the data generated in the first cell under "Multinomial Logit" above.
<ASSISTANT_TASK:>
Python Code:
import os; os.chdir('../choicemodels')
import choicemodels
import numpy as np
import pandas as pd
import statsmodels.api as sm  # for binary logit
from collections import OrderedDict  # for MNL model specifications
Explanation: Demo of the ChoiceModels library
For Binary Logit and Multinomial Logit, including sampling of alternatives.
To install ChoiceModels, git clone the repository (https://github.com/ual/choicemodels).
End of explanation
# Import or generate estimation data
Y = np.random.randint(2, size=50)  # 50x1 vector of random 0's and 1's
X = np.random.rand(50, 3)  # 50x3 matrix of random floats
data = pd.DataFrame(data=X, columns=['x1','x2','x3'])
data['y'] = Y
print(data.describe())
# Fit a model
specification = 'y ~ x1 + x2 + x3'
m = sm.Logit.from_formula(specification, data)
results = m.fit()
print(results.summary())
Explanation: Binary Logit
End of explanation
# Import or generate estimation data
def rand(len, min, max):
     Generate `len` random floats uniformly distributed from `min` to `max` 
    return (max - min) * np.random.rand(len) + min
numalts = 50  # alternatives
X = np.concatenate((rand(numalts/2, 0, 10), rand(numalts/2, 100, 110)))
numobs = 1000  # agents/observations
beta = np.zeros(1000) + 1.5
U = [[beta[n]*x + np.random.gumbel() for x in X] for n in range(numobs)]  # utility matrix
choices = [np.argmax(a) for a in U]
Explanation: Multinomial Logit
End of explanation
# Set up the estimation dataset in long format
d = [[n, i, int(choices[n]==i), X[i]] for n in range(numobs) for i in range(numalts)]
df = pd.DataFrame(d, columns=['obs_id', 'alt_id', 'chosen', 'x'])
print(df.describe())
# Set up model spec
spec = OrderedDict([('x', 'all_same')])
labels = OrderedDict([('x', 'beta_x')])
def estimate_model(init_val):
    
    Initialize and fit a model, returning it as an object. Will use the 
    current values of `df`, `spec`, and `labels`.
    
    m = choicemodels.MNLogit(data = df, 
                             alt_id_col = 'alt_id',
                             obs_id_col = 'obs_id', 
                             choice_col = 'chosen', 
                             specification = spec, 
                             names = labels)
    results = m.fit_mle(init_vals = np.array([init_val]))
    return results
%%time
results = estimate_model(init_val = 1.2)
print(results.summary())
Explanation: This is what the data looks like:
N = 1000 agents/observations with true taste coefficients in array "beta"
J = 50 alternatives with single attributes in array "X"
N choice outcomes in array "choices"
End of explanation
def alts(obs_id, C, K):
    
    This function generates a restricted choice set D for a particular
    observation. Expects list `C` of alternatives to sample from (either
    the full choice set or a stratrum), int `K` alternatives to sample,
    and list `choices` of the alt_id chosen for each obs_id. Returns list 
    of K alt_id's including the chosen one.
    
    chosen = choices[obs_id]  # id of chosen alternative
    unchosen = [i for i in C if chosen != i]  # id's of unchosen alts
    sample_unchosen = np.random.choice(unchosen, size=K-1, replace=False).tolist()
    return np.sort([chosen] + sample_unchosen)
# Set up the estimation dataset, which can use the same spec as earlier
C = range(numalts)  # choice set to sample from
K = 10
d = [[n, i, int(choices[n]==i), X[i]] for n in range(numobs) for i in alts(n, C, K)]
df = pd.DataFrame(d, columns=['obs_id', 'alt_id', 'chosen', 'x'])
print df.describe()
%%time
results = estimate_model(init_val = 1.2)
print results.summary()
Explanation: MNL with random sampling of alternatives
This example reuses the data generated in the first cell under "Multinomial Logit" above.
End of explanation
<END_TASK>