Модели классификаторов

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 13 фев 2019, 12:37

Olej писал(а):Дальше реализую модели классификации на этих (некоторых) наборах данных...
- dataset.py :

Код: Выделить всё

# -*- coding: utf-8 -*-
try: 
    import urllib.request as url
except ImportError:
    import urllib as url
import os
import subprocess
from sklearn import metrics, neighbors 
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier 

def version():
    return 'version 0.05'
#-----------------------------------------------------------------------   
def gunzip( response, zname, step = 100000 ):
    fw = os.open( zname, os.O_WRONLY | os.O_TRUNC | os.O_CREAT )
    data = response.read()
    os.write( fw, data )
    os.close( fw )
    proc = subprocess.Popen( [ 'gunzip', '-kfq', zname ] )
    dname = zname[ :zname.rfind( '.' ) ]
    fr = os.open( dname, os.O_RDONLY ) 
    print( '{} => {}'.format( zname, dname ) )  
    data = ''
    while True:
        d = os.read( fr, step )
        data += d.decode( 'utf-8' ) 
        if len( d ) < step: break
    os.close( fr )
    return ( data.splitlines() )
#-----------------------------------------------------------------------
def loadtxt( dataset, delimiter = ',', help = True ):      # load selected dataset
    def get( str ):
        try:
            return float( str )
        except Exception:
            return 0.0 
    if help:        
        print( 'dataset URL: {}'.format( dataset[ 0 ] ) )
    try: 
        response = url.urlopen( dataset[ 0 ] )             # download from URL
    except IOError as err: 
        print( 'wrong URL: {}'.format( err ) )
        sys.exit( 1 )

    fname = dataset[ 0 ].split( os.sep )[ -1 ]
    if 'Z' == fname.split( '.' )[ -1 ]:                    # gzip archive
        data = gunzip( response, fname )
    else:
        data = response.read().decode( 'utf-8' ).splitlines()

    arg = []; fun = []
    for line in data:
        lst = list( map( get, line.split( delimiter ) ) ) 
        arg.append( lst[ dataset[ 2 ] : dataset[ 3 ] + 1 ] )
        fun.append( lst[ dataset[ 1 ] ] )  
    return ( arg, fun )
#-----------------------------------------------------------------------
class model:                                               # classification models
    title = ( 'K Neighbors Classifier'  ,
              'Logistic Regression'     , 
              'Gaussian NB'             ,
              'Decision Tree Classifier',
              'Support Vector Machines',
              'RandomForest' )
    funct = ( neighbors.KNeighborsClassifier( n_neighbors = 5, weights = 'distance' ),
              LogisticRegression( solver = 'lbfgs', multi_class = 'auto', max_iter = 3000 ),
              GaussianNB(), 
              DecisionTreeClassifier(),    
              SVC( gamma = 'auto' ), 
              RandomForestClassifier( n_estimators = 100 )
            ) 
#-----------------------------------------------------------------------
dbase = (                                                  # url-s with dataset
    ( 'http://archive.ics.uci.edu/ml/machine-learning-databases/glass/glass.data',
      10, 1, 9 ), 
    ( 'http://archive.ics.uci.edu/ml/machine-learning-databases/zoo/zoo.data',
      17, 1, 16 ),
    ( 'http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',
      0, 1, 14 ), 
    ( 'http://archive.ics.uci.edu/ml/machine-learning-databases/spambase/spambase.data',
      57, 0, 56 ),
    ( 'http://archive.ics.uci.edu/ml/machine-learning-databases/waveform/waveform.data.Z',
      21, 0, 20 )  
        )
    
def get_data( i ): 
    return dbase[ i ]
#-----------------------------------------------------------------------  
- mlclass.py :

Код: Выделить всё

#!/usr/bin/python2 
# -*- coding: utf-8 -*- 
import os, sys, argparse
from dataset import *

parser = argparse.ArgumentParser() 
parser.add_argument( '-b', '--base', required = False, type = int, 
                     default = 0, help = 'data base number' )
parser.add_argument( '-m', '--model', required = False, 
                     default = '0', help = 'select model numbers' )
parser.add_argument( '-v', '--verbose', action = 'count', 
                     default = 0, help = 'increase output verbosity' )
args = vars( parser.parse_args() )

debug = int( args[ 'verbose' ] )                       # verbose level
print( version() )
if debug > 0: 
    print( args )

X, y = loadtxt( get_data( args[ 'base' ] ) )           # load selected dataset
if debug > 0: 
    print( y )
    if debug > 1: 
        print( X )
print( '{} instances with {} dimensions into {} classes: {}'.
       format( len( X ), len( X[ 0 ] ), len( set( y ) ), list( set( y ) ) ) )

#-----------------------------------------------------------------------
def model_list( str ):
    mpos = str.split( ',' )
    for sn in mpos:
        def add( i ):
            global mlist
            mlist[ i ] = model.funct[ i ]
        n = sn.find( '-' )
        if -1 == n:
            try: add( int( sn ) )
            except Exception: pass
        else:
            print( n, sn[ :n ], sn[ n+1: ] )
            try:
                for m in range( int( sn[ :n ] ), int( sn[ n+1: ] ) + 1 ):
                    add( m )
            except Exception: pass
#-----------------------------------------------------------------------

mlist = [ None for i in range( len( model.title ) ) ]  # select models             
model_list( args[ 'model' ] )
if debug > 0:
    for m in mlist: 
        print( 'model: {}'.format( m ) ) 

for i in range( len( mlist ) ):                        # apply models
    if None == mlist[ i ]: continue
    print( model.title[ i ] )
    fmodel = mlist[ i ] 
    fmodel.fit( X, y )
    #print(model)
    expected = y        # make predictions
    predicted = fmodel.predict( X )
    # summarize the fit of the model
    print( metrics.classification_report( expected, predicted ) )
    print( metrics.confusion_matrix( expected, predicted ) )
Пока здесь 6 моделей классификации + 5 URL баз данных.
Вложения
dataset.py
(4.74 КБ) 85 скачиваний
mlclass.py
(3.5 КБ) 74 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 13 фев 2019, 12:41

Olej писал(а):Пока здесь 6 моделей классификации + 5 URL баз данных.
-b ... - номер базы данных; -m ... - список номеров моделей:

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning$ ./mlclass.py -h
usage: mlclass.py [-h] [-b BASE] [-m MODEL] [-v]

optional arguments:
  -h, --help            show this help message and exit
  -b BASE, --base BASE  data base number
  -m MODEL, --model MODEL
                        select model numbers
  -v, --verbose         increase output verbosity

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning$ ./mlclass.py -b4 -m0,5
version 0.05
dataset URL: http://archive.ics.uci.edu/ml/machine-learning-databases/waveform/waveform.data.Z
waveform.data.Z => waveform.data
5000 instances with 21 dimensions into 3 classes: [0.0, 1.0, 2.0]
K Neighbors Classifier
              precision    recall  f1-score   support

         0.0       1.00      1.00      1.00      1657
         1.0       1.00      1.00      1.00      1647
         2.0       1.00      1.00      1.00      1696

   micro avg       1.00      1.00      1.00      5000
   macro avg       1.00      1.00      1.00      5000
weighted avg       1.00      1.00      1.00      5000

[[1657    0    0]
 [   0 1647    0]
 [   0    0 1696]]
RandomForest
              precision    recall  f1-score   support

         0.0       1.00      1.00      1.00      1657
         1.0       1.00      1.00      1.00      1647
         2.0       1.00      1.00      1.00      1696

   micro avg       1.00      1.00      1.00      5000
   macro avg       1.00      1.00      1.00      5000
weighted avg       1.00      1.00      1.00      5000

[[1657    0    0]
 [   0 1647    0]
 [   0    0 1696]]

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 13 фев 2019, 12:51

Olej писал(а):Пока здесь 6 моделей классификации + 5 URL баз данных.
И оценка значимости аргументов + отбор N самых значащих из всех:
- signify.py :

Код: Выделить всё

#!/usr/bin/python2 
# -*- coding: utf-8 -*- 
import os, sys, argparse
from sklearn import metrics 
from sklearn.linear_model import LogisticRegression
from sklearn import preprocessing
from dataset import *

parser = argparse.ArgumentParser() 
parser.add_argument( '-b', '--base', required = False, type = int, 
                     default = 0, help = 'data base number' )
parser.add_argument( '-n', '--normalise',  action = 'store_true', 
                     help = 'normalise attributes' )
parser.add_argument( '-s', '--standardize',  action = 'store_true', 
                     help = 'standardize attributes' )
parser.add_argument( '-e', '--eval',  required = False, type = int, 
                     default = 0, help = 'evaluate the significance of the attributes' )
parser.add_argument( '-i', '--iterate',  required = False, type = int, 
                     default = 2000, help = 'number of iterations' )
parser.add_argument( '-v', '--verbose', action = 'count', 
                     default = 0, help = 'increase output verbosity' )
args = vars( parser.parse_args() )

debug = int( args[ 'verbose' ] )                       # verbose level
if debug > 0: 
    print( version() )
    print( args )

X, y = loadtxt( get_data( args[ 'base' ] ) )           # load selected dataset
if debug > 0: 
    print( y )
    if debug > 1: 
        print( X )
print( '{} instances with {} dimensions into {} classes: {}'.
       format( len( X ), len( X[ 0 ] ), len( set( y ) ), list( set( y ) ) ) )

if args[ 'normalise' ]:                                # normalize the data attributes
    X = preprocessing.normalize( X )
if args[ 'standardize' ]:                              # standardize the data attributes
    X = preprocessing.scale( X )

if args[ 'eval' ] > 0:                                 # calculation of signs informativeness
    from sklearn.ensemble import ExtraTreesClassifier
    fmodel = ExtraTreesClassifier( n_estimators = 100 )
    fmodel.fit( X, y )
    # display the relative importance of each attribute
    print( 'relative importance: {}'.format( fmodel.feature_importances_ ) )
    from sklearn.feature_selection import RFE
    print( 'wait...' )
    fmodel = LogisticRegression( solver = 'lbfgs', multi_class = 'auto',
                                 max_iter = int( args[ 'iterate' ] ) )
    # create the RFE model and select N attributes
    rfe = RFE( fmodel, int( args[ 'eval' ] ) )         # Recursive Feature Elimination - find the best subset
    rfe = rfe.fit( X, y )
    print( rfe.support_ )                              # summarize the selection of the attributes
    print( rfe.ranking_ )
    sys.exit()

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning$ time ./signify.py -b4 -e4
dataset URL: http://archive.ics.uci.edu/ml/machine-learning-databases/waveform/waveform.data.Z
waveform.data.Z => waveform.data
5000 instances with 21 dimensions into 3 classes: [0.0, 1.0, 2.0]
relative importance: [0.01878051 0.01990646 0.02514121 0.04127729 0.06106701 0.06528184
 0.06395634 0.04892396 0.05651917 0.06801552 0.0867656  0.06679843
 0.05624313 0.05062932 0.05306694 0.05404963 0.05249791 0.0457818
 0.02656516 0.02018933 0.01854343]
wait...
[False False False False  True False  True False False  True  True False
 False False False False False False False False False]
[17 15 14 11  1  7  1  2  6  1  1  3  5  9  8 12  4 10 13 16 18]

real	0m5,390s
user	0m4,007s
sys	0m0,109s
Вот здесь из 21 аргументов зависимости вот тех 5000 данных - выделены 4 самых значащих.
И это вычисление совсем не так быстро...
Вложения
signify.py
(3.76 КБ) 76 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 14 фев 2019, 12:22

Olej писал(а):Это всё модельные данные, искусственно генерируемые.
Ещё один характерный и часто интересующий класс задач - различение рукописных цифр.
Для работы с наборами таких данных в пакете sklearn есть соответствующий класс:

Код: Выделить всё

from sklearn import datasets
...
digits = datasets.load_digits()
...

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 14 фев 2019, 12:32

Olej писал(а): Для работы с наборами таких данных в пакете sklearn есть соответствующий класс:
- digits.py :

Код: Выделить всё

#!/usr/bin/python3
# -*- coding: utf-8 -*- 
import sys, argparse
from functools import reduce
from sklearn import datasets
import matplotlib.pyplot as plt
from dataset import *

def histog( tl ):
    d = {} 
    for n in range( 10 ):
        d[ n ] = sum( map( lambda a: int( a == n ), tl ) ) 
    return d

parser = argparse.ArgumentParser() 
parser.add_argument( '-l', '--learn', required = False, type = int, 
                     default = 10, help = 'digits in learn' )
parser.add_argument( '-t', '--test', required = False, type = int, 
                     default = 10, help = 'digits in learn' )
parser.add_argument( '-m', '--model', required = False, 
                     default = '0', help = 'select model numbers' )
parser.add_argument( '-v', '--verbose', action = 'count', 
                     default = 0, help = 'increase output verbosity' )
args = vars( parser.parse_args() )
debug = int( args[ 'verbose' ] )                       # verbose level
if debug: print( version() )

digits = datasets.load_digits()
l = len( digits.images )                               # dataset size
print( 'dataset size {}: {}'.format( l, histog( digits.target ) ) )
n = int( args[ 'learn' ] )                             # training size
if n > l:
    print( '{} - too large'.format( n ) )
    sys.exit( 1 )
t = int( args[ 'test' ] )                              # test size
if t + n > l:
    print( '{} - too large'.format( t ) )
    sys.exit( 1 )

if debug:
    print( args )
    if debug > 1:
        print( 'target {} {}: {}'.format( len( digits.target ), type( digits.target[ 0 ] ), digits.target ) )
        print( 'images {} {}'.format( len( digits.images ), type( digits.images[ 0 ] ) ) )
        print( digits.images[ 0 ] )
        print( 'images dimension={} size={}'.format( digits.images[ 0 ].ndim, digits.images[ 0 ].shape ) )
        plt.figure( digits.target[ n - 1 ] )
        plt.imshow( digits.images[ n - 1 ], cmap = plt.cm.gray_r, interpolation = 'nearest' )
        plt.show()

#print( histog( digits.target ) )

try:
    md = model.funct[ int( args[ 'model' ] ) ]
    tl = model.title[ int( args[ 'model' ] ) ] 
except Exception: 
    md = model.funct[ 0 ]
    tl = model.title[ 0 ] 

X = digits.data[ 0 : n ]
y = digits.target[ 0 : n ]
md.fit( X, y )                                         # train a classifier

Z = digits.data[ ( n + 1 ) : ( n + t + 1 ) ]
tst = digits.target[ ( n + 1 ) : ( n + t + 1 ) ]

if debug > 1: print( tst )

res = md.predict( Z )
if debug > 1: print( res )

e = reduce( lambda a, b: a + b, map( lambda a, b: int( a != b ), tst, res ) ) 
print( 'recognition errors: {}, relatively {} ({:.3f}%)'.format( e, float( e ) / t, float( e ) / t * 100 ) )

if debug:
    d = { i:0 for i in range( 10 ) } 
    for a, b in zip( tst, res ):
        if a != b: d[ a ] += 1
    for i in range( 10 ):
        if d[ i ] == 0: del d[ i ] 
    print( d )
Вот так происходит распознавание/классификация:

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning/digits$ python3 ./digits.py -l200 -t100 -m0 -v
version 0.05
dataset size 1797: {0: 178, 1: 182, 2: 177, 3: 183, 4: 181, 5: 182, 6: 181, 7: 179, 8: 174, 9: 180}
{'learn': 200, 'test': 100, 'model': '0', 'verbose': 1}
recognition errors: 6, relatively 0.06 (6.000%)
{1: 2, 5: 2, 9: 2}

Здесь первые 200 изображений цифр, из представленных в наборе 1797, используется для обучения классификатора, а следующие 100 распознаются, из которых 6 распознаны ошибочно.

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning/digits$ ./digits.py -h
usage: digits.py [-h] [-l LEARN] [-t TEST] [-m MODEL] [-v]

optional arguments:
  -h, --help            show this help message and exit
  -l LEARN, --learn LEARN
                        digits in training
  -t TEST, --test TEST  digits in recognition
  -m MODEL, --model MODEL
                        select model numbers
  -v, --verbose         increase output verbosity
А вот так - с большей степенью детализации отладочной информации:

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/MachineLearning/digits$ python3 ./digits.py -l200 -t100 -m0 -vv
version 0.05
dataset size 1797: {0: 178, 1: 182, 2: 177, 3: 183, 4: 181, 5: 182, 6: 181, 7: 179, 8: 174, 9: 180}
{'learn': 200, 'test': 100, 'model': '0', 'verbose': 2}
target 1797 <class 'numpy.int64'>: [0 1 2 ... 8 9 8]
images 1797 <class 'numpy.ndarray'>
[[ 0.  0.  5. 13.  9.  1.  0.  0.]
 [ 0.  0. 13. 15. 10. 15.  5.  0.]
 [ 0.  3. 15.  2.  0. 11.  8.  0.]
 [ 0.  4. 12.  0.  0.  8.  8.  0.]
 [ 0.  5.  8.  0.  0.  9.  8.  0.]
 [ 0.  4. 11.  0.  1. 12.  7.  0.]
 [ 0.  2. 14.  5. 10. 12.  0.  0.]
 [ 0.  0.  6. 13. 10.  0.  0.  0.]]
images dimension=2 size=(8, 8)
[5 0 9 5 2 8 2 0 0 1 7 6 3 2 1 7 3 1 3 9 1 7 6 8 4 3 1 4 0 5 3 6 9 6 1 7 5
 4 4 7 2 8 2 2 5 5 4 8 8 4 9 0 8 9 8 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
 9 0 1 2 3 4 5 6 7 8 9 0 9 5 5 6 5 0 9 8 9 8 4 1 7 7]
[5 0 9 5 2 8 2 0 0 1 7 6 3 2 1 7 3 1 3 9 1 7 6 8 4 3 1 4 0 5 3 6 9 6 1 7 5
 4 4 7 2 8 2 2 5 5 4 8 8 4 9 0 8 9 8 0 8 2 3 4 9 6 7 8 5 0 1 2 3 4 5 6 7 8
 7 0 1 2 3 4 5 6 7 8 9 0 9 5 5 6 9 0 9 8 9 8 4 8 7 7]
recognition errors: 6, relatively 0.06 (6.000%)
{1: 2, 5: 2, 9: 2}
С отображении того (для визуализации), как отрисовывается изображение цифры (на грани между обучающей и тестируемой последовательностями):
d9-2.png
d9-2.png (14.76 КБ) 1500 просмотров
Вложения
digits.py
(2.82 КБ) 72 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модели классификаторов

Непрочитанное сообщение Olej » 15 фев 2019, 00:39

Olej писал(а): Ещё один характерный и часто интересующий класс задач - различение рукописных цифр.
А вот пример распознавания этого же dataset из самих экзамплов проекта Scikit-Learn: Recognizing hand-written digits:
Изображение

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя