20171030 - TNUI-UB/grupA-sessions GitHub Wiki

Parcial dimecres 8 de novembre

  • Consistirà en teoria i pràctiques. Molt probablement, sereu tota l'estona (màx 3 h) en una aula d'informàtica i allà fareu la teoria i la pràctica.

  • Part pràctica

    • reviseu el que hem fet fins ara. Entra pràctica 0 i 1.
    • no heu de memoritzar res, els algorismes s'explicaran.
  • Dubtes?

Pràctica 1: Apriori

  • Revisem alguna funció: filter_by_support(), naive() i generate_next().
def filter_by_support(df, all_sets, min_support):
    """
    Donades totes les combinacions i el suport mínim, retorna un altre
    DataFrame amb solament aquelles combinacions que tenen un suport
    major al mínim
    
    :param df: DataFrame de dades
    :param all_sets: DataFrame de combinacions, amb `order_id` i `products`
    :param min_support: Suport mínim de les combinacions
    :return: DataFrame amb estructura igual que `all_sets` però filtrat segons el
        suport mínim
    """
    counts = all_sets['products'].value_counts()
    return all_sets[all_sets['products'].isin(counts[counts >= min_support].index)]
def naive(df, target_n, min_support):
    """
    Donat el conjunt original, la $n$ objectiu i el suport mínim,
    calcula aquelles combinacions freqüents de forma Naive, utilitzant
    les funcions programades adalt.
    
    :param df: DataFrame de dades
    :param target_n: $n$ objectiu
    :param min_support: Suport mínim de les combinacions
    :return: DataFrame de combinacions, amb `order_id` i `products`, amb
        combinacions de tamany $n$ i filtrat pel suport mínim
    """
    all_sets = get_all_n_sets(df, target_n)
    filtered = filter_by_support(df, all_sets, min_support)
    return filtered
def generate_next(previous, n_prev):
    """
    Donades les combinacions de tamany $n-1$ genera les de tamany $n$. Ho fa
    seguint les regles d'Apriori (ie. si anteriorment en l'ordre 1 i tamany 2 teníem solament 
    (1,2),(1,4),(4,5) i ara volem generar les de tamany 3, la combinació (1,4,5) no és vàlida,
    doncs no teníem originalment la (1,5)!
    
    :param previous: DataFrame de combinacions del tamany previ, amb `order_id` i `products`
    :param n_prev: Tamany previ de les combinacions present en el DataFrame `previous`
    :return: DataFrame de combinacions de tamany $n$, amb `order_id` i `products`
    """
    def wrapped():
        unique = set(previous['products'])
        
        for order_id in previous['order_id'].unique():
            prods = previous[previous['order_id'] == order_id]['products']

            for prod_1 in prods:
                for prod_2 in prods:
                    comb = sorted(set(itertools.chain(prod_1, prod_2)))
                    if len(comb) == n_prev + 1:
                        if all(c in unique for c in itertools.combinations(comb, n_prev)):
                            yield order_id, tuple(comb)
                        
    data = pd.DataFrame(wrapped())
    data.columns = ['order_id', 'products']
    data = data.drop_duplicates(keep='first')
    return data

Pràctica 2: Chatbot

Chatbot de Telegram. A lliurar abans del 13 de novembre. Ull! La setmana anterior és la de parcials, així que tindrem dues sessions per a treballar-hi. Avui és la darrera

En aquesta pràctica aprendrem a treballar amb una API i de forma asíncrona mitjançant Python 3.5.


  • Idea: per treballar amb parelles amb un token cadascú, poseu el vostre token al fitxer TOKEN i afegiu-lo a .gitignore. Així, quan pugeu codi al repositori no sobreescriureu el de l'altre.

1. Persistència de sessions

Aquesta part l'implementem desacoblada del bot.

Informació guardada a:

{
  'id': 1234,
  'status': 'FLAGGING',
  'messages': ['/start', 'llet', 'ous 6', '/done'],
  'products': [
    {
      'id': 'llet',
      'status': 'PENDING',
      'qty': 1
    },
    {
      'id': 'ous',
      'status': 'PENDING',
      'qty': 6
    },
  ]
}

Per afegir un nou element llet, el que hem de fer és veure si a contingut[user_id]['products'] existeix un element amb id == "llet".

Casuístiques:

/start    => usuari en estat 'ADDING'
llet 3    => afegim llet->3
llet 4    => llet->7
ous 2     => ous->2
/list     => retornem  llet->7, ous->2
ous 1     => ous->3
/done     => envia el mateix que /list
             usuari en estat 'FLAGGING'
             a partir d'aquí els productes es marcaran com a "BOUGHT".
poma 3    => ERROR! ja no es poden afegir productes
ous       => marquem el producte 'ous' com a comprat: ous.status = 'BOUGHT'
ous       => ERROR! ja havíem comprat el producte 'ous'
formatge  => ERROR! 'formatge' no és a la llista de productes
/start    => eliminem tota la info de l'usuari
  • El missatge /start el podeu guardar o no. En l'enunciat diem ambdues coses, així que ho deixem a la vostra elecció.