Algoritmo fuzzy per raggruppare i dati

6

Ho dati che indicano quali argomenti ogni studente ha ragione / torto in una valutazione:

| Student | Topic 1 | Topic 2 | Topic 3 | Topic 4 | Topic 5 | ... (perhaps 30 topics)
|    1    |    T    |    T    |    T    |    T    |    F    |
|    2    |    F    |    T    |    F    |    T    |    T    |
|    3    |    T    |    F    |    F    |    T    |    T    |
|    4    |    T    |    F    |    F    |    T    |    F    |
|    5    |    F    |    F    |    T    |    T    |    F    |

... (perhaps 200 students)

Mi piacerebbe progettare un algoritmo per identificare gruppi di studenti con simili aree di incomprensione . Ad esempio, potrebbe restituire:

  • 70 studenti che hanno ottenuto almeno l'80% degli argomenti 4, 6, 7, 12, 14, 19, 20, 21 e 25 non corretti.
  • 56 studenti che hanno ricevuto almeno l'80% degli argomenti 4, 8, 10, 11, 19 e 24 non corretti.
  • ecc.

Avrebbe bisogno di cercare il maggior numero possibile di sottoinsiemi di argomenti, subordinatamente alla corrispondenza di un numero minimo di studenti.

Mi rendo conto che non si tratta di un problema ben definito, quindi gradirei ricevere aiuto nel dichiararlo in modo più chiaro, oltre a suggerimenti per una progettazione di algoritmi (o un approccio di apprendimento automatico?).

    
posta James 20.04.2016 - 19:37
fonte

3 risposte

2

È necessario un algoritmo di clustering. L'idea di base è che vuoi trattare i dati di ogni studente come una coordinata n-dimensionale, ad es. Coordinata tridimensionale in questo caso.

Quindi se avessi 3 dimensioni, potresti avere uno studente in x, y, z: 1,1,0; un altro a 0,1,1, ecc.

La distanza tra di loro potrebbe essere trovata usando la formula euclidea.

La distanza tra le corde ndimensionali può essere trovata con la stessa formula:

link

Tuttavia, molto spesso in questo tipo di problemi di clustering, la formula euclidea potrebbe non funzionare al meglio, e invece potresti avere risultati migliori usando la distanza di manhattan:

link

Uno degli algoritmi semplici e facili per il clustering è k-means clustering:

link

La popolare e ben documentata libreria per l'apprendimento automatico dei pitoni si chiama scikit-learn, e include molti tipi di clustering, k-means che ho menzionato sopra e molti altri:

link

link

Spero che questo aiuti! Ho implementato il clustering semplice come esercizio personale, ma non su dati reali n-dimensionali, quindi questo è tutto basato su ciò che ho letto (principalmente il libro di apprendimento automatico "Data Smart", che è molto buono ma usa le formule Excel per illustrazione che rappresenta una grossa lacuna dal mio punto di vista, come un programmatore python).

Fammi sapere se hai domande ..

[MODIFICA: una sfumatura da considerare è se si desidera trattare le corrispondenze tra gli studenti che considerano un argomento più significativo, meno significativo o uguale alla corrispondenza quando ricevono un argomento errato. Se sono uguali, puoi semplicemente utilizzare una delle metriche di distanza sopra indicate, se vuoi che una di esse sia più significativa, dovrai apportare alcune modifiche.

Questo è chiamato "calcolo della distanza asimmetrico". Un esempio usato nel libro è "distanza coseno". Penso che gli scikit-learn avranno delle metriche di distanza che possono aiutare con questo, cercare le metriche "spazi vettoriali con valore booleano", è necessario leggerle e probabilmente sperimentarne l'uso. "

    
risposta data 21.05.2016 - 06:08
fonte
1

A partire da permutazioni e combinazioni , penso che siamo interessati alle combinazioni:

Per 30 argomenti, avresti il conteggio follower delle combinazioni per ogni dimensione:

(In altre parole ci sono 30 combinazioni di dimensioni 1 e 435 combinazioni di dimensione 2 (anche 435 di dimensioni 28 come risulta)).

  1. 30
  2. 435
  3. 4060
  4. 27405
  5. 142506
  6. 593.775
  7. 2035800
  8. 5852925
  9. 14307150
  10. 30045015
  11. 54627300
  12. 86493225
  13. 119759850
  14. 145422675
  15. 155117520
  16. 145422675
  17. 119759850
  18. 86493225
  19. 54627300
  20. 30045015
  21. 14307150
  22. 5852925
  23. 2035800
  24. 593.775
  25. 142506
  26. 27405
  27. 4060
  28. 435
  29. 30
  30. 1

Penso che potresti generare ognuna delle combinazioni per ciascuna dimensione della combinazione da 1 a 30. Puoi google "generare tutte le combinazioni" e, inoltre, ne ho allegato uno che ho montato sotto.

Per ogni dimensione di combinazione, potremmo trovare le combinazioni e trovarne le occorrenze tra gli studenti e ordinarle in base al loro conteggio. Potresti avere un taglio di interesse, mantenendo solo la parte superiore del% per ogni dimensione.

Possiamo memorizzare il punteggio di ogni studente con un bit. Quindi, per 30 argomenti, abbiamo bisogno di 30 bit per studente. Su una macchina a 64 bit, possiamo memorizzare fino a 64 bit in un singolo numero intero.

Possiamo rappresentare una combinazione anche come un intero, i cui bit sono impostati per rappresentare quali elementi sono nella combinazione. In altre parole, una combinazione di dimensione 6 è rappresentata da un intero che ha esattamente 6 dei suoi bit impostati.

Quindi, data una combinazione, possiamo testare ciascuno dei ~ 200 studenti per la corrispondenza con una semplice operazione AND bitwise logica seguita da un confronto.

for ( var i = 0; i < 200; i++ )
    if ( (studentScores [i] & currentCombinaton) == currentCombination )
       // this combination matched for this student.

NOTA come scritto questo sta controllando le combinazioni di successo e non le combinazioni di errori, ma questo è facilmente reversibile (usando == 0 invece di == currentCombination ).

Quindi, questo è un inizio.

Penso che potresti fare un'analisi delle combinazioni l'una rispetto all'altra, ad esempio quali combinazioni popolari di dimensione 4 o 5 si trovano nelle popolari combinazioni di dimensione 16.

Di seguito è riportato un programma C # che ho scritto che genera combinazioni di valori T / F come bit mask. Potresti inserire il generatore combinato in un ciclo di dimensioni e utilizzare il ciclo di occorrenze studente sopra per ciascuna di queste dimensioni.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication17
{
    class Program
    {
        static ulong NextCombination ( int outOf, ulong last )
        {
            int i;
            for ( i = 0; i < outOf; i++ )
            {
                if ( (last & (1UL << i)) != 0 )
                    break;
            }

            int j;
            for ( j = i + 1; j < outOf; j++ )
            {
                if ( (last & (1UL << j)) == 0 )
                    break;
            }

            // we alter the number by removing all the consecutive ones
            //  that occur followed by a zero (viewed from low order to high order)
            //  as in ...0111...
            // replace with a single 1
            //  as in ...1000... and set low bits to bits in a row, i.e.
            //  ...1000.....011

            int numberOfOnesInARowBeforeFirstZero = j - i;

            var onesMask = ((1UL << numberOfOnesInARowBeforeFirstZero) - 1) << i;
            last &= ~onesMask; // clear the series of one's

            last |= 1UL << j; // set the first zero bit after the ones in a row

            var lowOnesReplacement = (1UL << (numberOfOnesInARowBeforeFirstZero - 1)) - 1;
            last |= lowOnesReplacement; // set the lowest bits to make up for the cleared bits

            return last;
        }

        static void Main ( string [] args )
        {
            int comboSize = 3;
            int outOfSize = 30;

            int count = 1;

            ulong currentCombination = (1UL << comboSize) - 1;
            ulong lastCombination = currentCombination << (outOfSize - comboSize);
            System.Console.WriteLine ( "Last Combination for size " + comboSize + " is " + Convert.ToString ( (long) lastCombination, 2 ).PadLeft ( outOfSize, '0' ) );
            for ( ;; )
            {
                System.Console.WriteLine ( "Combination " + count + " is " + Convert.ToString ( (long) currentCombination, 2 ).PadLeft ( outOfSize, '0' ) );
                if ( currentCombination == lastCombination )
                    break;
                currentCombination = NextCombination ( outOfSize, currentCombination );
                count++;
            }
            System.Console.ReadLine ();
        }
    }
}
    
risposta data 20.04.2016 - 23:56
fonte
0

It would need to seek the largest possible subsets of topics, subject to matching a minimum number of students.

Quindi hai essenzialmente 2 criteri. Diamo un'occhiata al "più grande sottoinsieme possibile" prima:

Questa è la forza bruta, sfortunatamente. In altre parole, non conosci il gruppo più grande fino a quando non hai comunicato tutti i risultati. (Tranne che potresti ottimizzare su set di dati molto grandi, ma per ora ignoriamolo.)

Quindi, iterate su tutti gli argomenti e sommate i voti. Quindi, assicurati che i voti superino il "minimo".

A questo punto hai tutti gli argomenti che hanno voti sufficienti. Un'ottimizzazione in questo processo è riconoscere che se l'argomento con il minor numero di voti supera il totale di tutti i voti rimanenti, allora puoi fermarti. Ma è probabile che l'approccio della forza bruta sia abbastanza veloce senza ottimizzazione a meno che il voto sia superiore a milioni.

Lo pseudo codice potrebbe essere:

 int topicVotes = 0;
 Array[Integer] topics = new Array[topics.size];
 for (i = 0; i < topics.size; i++) {
      for (j = 0; j < votes.size; j++) {
           if (votes[j] == true) topicVotes++;
      }
      if (topicVotes > minimum) topics[i] = topicVotes;
 }

Questo potrebbe non essere il modo migliore per implementarlo, ma dovrebbe illustrare come filtrare gli argomenti che non soddisfano il requisito minimo enfatizzando al contempo che la forza bruta è richiesta (nella maggior parte dei casi) per garantire che tutti gli argomenti incontrati il minimo è incluso.

    
risposta data 24.05.2016 - 08:38
fonte

Leggi altre domande sui tag