Pandas gruplandırılmış DataFrame'e Python işlevi uygulamak - hesaplamaları hızlandırmak için en etkili yaklaşım nedir?


9

Oldukça büyük Pandalar DataFrame ile uğraşıyorum - veri setim aşağıdaki dfdüzene benziyor :

import pandas as pd
import numpy  as np

#--------------------------------------------- SIZING PARAMETERS :
R1 =                    20        # .repeat( repeats = R1 )
R2 =                    10        # .repeat( repeats = R2 )
R3 =                541680        # .repeat( repeats = [ R3, R4 ] )
R4 =                576720        # .repeat( repeats = [ R3, R4 ] )
T  =                 55920        # .tile( , T)
A1 = np.arange( 0, 2708400, 100 ) # ~ 20x re-used
A2 = np.arange( 0, 2883600, 100 ) # ~ 20x re-used

#--------------------------------------------- DataFrame GENERATION :
df = pd.DataFrame.from_dict(
         { 'measurement_id':        np.repeat( [0, 1], repeats = [ R3, R4 ] ), 
           'time':np.concatenate( [ np.repeat( A1,     repeats = R1 ),
                                    np.repeat( A2,     repeats = R1 ) ] ), 
           'group':        np.tile( np.repeat( [0, 1], repeats = R2 ), T ),
           'object':       np.tile( np.arange( 0, R1 ),                T )
           }
        )

#--------------------------------------------- DataFrame RE-PROCESSING :
df = pd.concat( [ df,
                  df                                                  \
                    .groupby( ['measurement_id', 'time', 'group'] )    \
                    .apply( lambda x: np.random.uniform( 0, 100, 10 ) ) \
                    .explode()                                           \
                    .astype( 'float' )                                    \
                    .to_frame( 'var' )                                     \
                    .reset_index( drop = True )
                  ], axis = 1
                )

Not: Minimum bir örneğe sahip olmak amacıyla, kolayca alt gruplara ayrılabilir (örneğin ile df.loc[df['time'] <= 400, :]), ancak yine de verileri simüle ettiğim için orijinal boyutun daha iyi bir genel bakış sağlayacağını düşündüm.

Tarafından tanımlanan her grup ['measurement_id', 'time', 'group']için aşağıdaki işlevi çağırmak gerekir:

from sklearn.cluster import SpectralClustering
from pandarallel     import pandarallel

def cluster( x, index ):
    if len( x ) >= 2:
        data = np.asarray( x )[:, np.newaxis]
        clustering = SpectralClustering( n_clusters   =  5,
                                         random_state = 42
                                         ).fit( data )
        return pd.Series( clustering.labels_ + 1, index = index )
    else:
        return pd.Series( np.nan, index = index )

Performansı artırmak için iki yaklaşım denedim:

Panda paralel paket

İlk yaklaşım hesaplamaları pandarallelpaket kullanarak paralelleştirmekti :

pandarallel.initialize( progress_bar = True )
df \
  .groupby( ['measurement_id', 'time', 'group'] ) \
  .parallel_apply( lambda x: cluster( x['var'], x['object'] ) )

Bununla birlikte, çok fazla RAM tükettiği ve hesaplamalarda tüm çekirdekler kullanılmadığı için ( pandarallel.initialize()yöntemde açıkça çekirdeklerin sayısını belirtmesine rağmen), bu durumun optimal olmadığı görülmektedir . Ayrıca, bunun için bir neden bulma şansım olmasa da, bazen hesaplamalar çeşitli hatalarla sonlandırılır (muhtemelen RAM eksikliği?).

PySpark Pandalar UDF

Spark için tamamen yeni olmama rağmen bir Spark Pandas UDF de verdim. İşte benim girişimim:

import findspark;  findspark.init()

from pyspark.sql           import SparkSession
from pyspark.conf          import SparkConf
from pyspark.sql.functions import pandas_udf, PandasUDFType
from pyspark.sql.types     import *

spark = SparkSession.builder.master( "local" ).appName( "test" ).config( conf = SparkConf() ).getOrCreate()
df = spark.createDataFrame( df )

@pandas_udf( StructType( [StructField( 'id', IntegerType(), True )] ), functionType = PandasUDFType.GROUPED_MAP )
def cluster( df ):
    if len( df['var'] ) >= 2:
        data = np.asarray( df['var'] )[:, np.newaxis]
        clustering = SpectralClustering( n_clusters   =  5,
                                         random_state = 42
                                         ).fit( data )
        return pd.DataFrame( clustering.labels_ + 1,
                             index = df['object']
                             )
    else:
        return pd.DataFrame( np.nan,
                             index = df['object']
                             )

res = df                                           \
        .groupBy( ['id_half', 'frame', 'team_id'] ) \
        .apply( cluster )                            \
        .toPandas()

Ne yazık ki, performans da tatmin edici değildi ve bu konuda okuduğumdan, bu sadece Python'da yazılmış UDF işlevini kullanmanın yükü ve tüm Python nesnelerini Spark nesnelerine ve geri dönüştürmeye ilişkin ihtiyaç olabilir.

Sorularım işte burada:

  1. Her iki yaklaşımım da olası darboğazları ortadan kaldıracak ve performansı artıracak şekilde ayarlanabilir mi? (örn. PySpark kurulumu, alt optimal işlemleri ayarlama vb.)
  2. Daha iyi bir alternatif var mı? Performans açısından sağlanan çözümlerle nasıl kıyaslanıyorlar?

2
Eğer araştırma yaptılar DASK ?
Danila Ganchar

1
Henüz değil, ama öneriniz için teşekkürler - Ben bir gitmek vereceğim
Kuba_

ne yazık ki birlikte çalışmadım dask(((bu yüzden benim yorumum sadece araştırma için tavsiye.)
Danila Ganchar

Performansla, hesaplamaların tamamlanabileceği zaman demek istedim.
Kuba_

Yanıtlar:


1

S : " Could ya benim yaklaşımların ayarlanabilir performansını mümkün darboğazları ortadan kaldırmak ve iyileştirmek için? (Örn PySpark kurulum vb optimumun işlemleri ayarlama) "

+1her iki hesaplama stratejisi için kurulum eklentisi genel giderlerinden bahsettiği için . Bu, her zaman başabaş bir noktaya işaret eder, ancak bundan sonra bir [SERIAL]strateji, olması gereken bir [TIME]Etki Alanı hızlandırmasının herhangi bir yararlı sevincini elde edebilir (yine de, genellikle, [SPACE]Etki Alanı maliyetleri izin verirse veya uygulanabilir kalırsa - evet RAM). .. böyle büyüklükteki bir cihazın, bütçenin ve diğer benzer gerçek dünya kısıtlamalarının varlığı ve bunlara erişim)

İlk olarak,
uçuş öncesi kontrol, biz kalkış öncesi
yeni, havai-sıkı Amdahl Kanunun formülasyonu şu anda geniş ilave Bunlardan ikisi dahil edebiliyor genel giderler ve başabaş dahil ulaşılabilir Speedup-noktalarını tahmin bu yansıtır bu noktadan itibaren paralel gitmenin anlamlı olabileceği (maliyet / etki, verimlilik anlamında) olabilir.
pSO + pTO

resim açıklamasını buraya girin

Oysa
ki değil burada bizim temel sorun .
Bu sırada:

Sonra,
bir hesaplama maliyetleri verilen SpectralClustering()Radyal Boltzmann Fonksiyon çekirdek kullanmak buraya gidiyor, ~ exp( -gamma * distance( data, data )**2 )bir bölünme hiçbir ilerleme var gibi görünüyor datagibi disjunct iş birimlerinin herhangi bir sayı üzerinde -Nesne distance( data, data )tanımı gereği, -bileşeni sahiptir ancak hepsini ziyaret data-elemanları (ref. iletişim maliyetlerini herhangi bir-to-herhangi bir değer-geçerek { process | node }-Dağıtık topolojileri bilinen nedenlerle, müthiş kötü ise değil kötü kullanımın söz { process | node }-Dağıtık işleme, değilse düz karşıtı desenler (bazı sırsızlar, hafızasız / halsiz, ancak bilgisayarlı kumaşlar hariç).

Bilgiçlikçi analistler için, evet - buna ekleyin (ve zaten kötü bir durum söyleyebiliriz ) - yine - herhangi bir herhangi bir k-aracı -işleme maliyeti , burada O( N^( 1 + 5 * 5 ) )bunun için N ~ len( data ) ~ 1.12E6+, bazılarına sahip olma isteğimize karşı akıllı ve hızlı işleme.

Ne olmuş yani?

Kurulum maliyetleri ihmal olmasa da, artan iletişim maliyetleri neredeyse Yukarıda genel hatlarıyla anlatılan girişimlerini kullanmaktan emin devre dışı herhangi iyileştirilmesi için bir pure- taşınmaya olacak [SERIAL]bazı forma süreç akışının sadece - [CONCURRENT]veya true- [PARALLEL]bazı iş-alt birimlerinin orkestrasyon , herhangi bir değerden geçen herhangi bir değer geçiş topolojisinin uygulanması (tandem çifti) zorunluluğu ile ilgili artan genel masraflar nedeniyle .

Eğer onlar için olmasaydı?

Bu, bir Bilişim Bilimi oksimoronu gibi görünüyor - mümkün olsa bile, önceden hesaplanmış herhangi bir mesafenin [TIME]maliyeti ( bu muazzam -Alan karmaşıklığı maliyetlerini "önceden" alacaktı (Nerede? Nasıl? diğer, önlenemeyen gecikme, bazı (şimdiye kadar bilinmeyen) tam gelecekte herhangi bir herhangi bir mesafe matrisinin artımlı birikimi tarafından olası bir gecikme maskelemesine izin verir mi?)), ancak bu mevcut maliyetleri, [TIME]- ve [SPACE]-Domains, onları azaltmak değil.

S : " Daha iyi bir alternatif var mı? "

Şimdiye kadar farkında olduğum tek şey, eğer problem başka bir QUBO formüle edilmiş, problem modaya yeniden formüle edilebiliyorsa, denemektir (ref .: Q uantum- U nconstrained- B inary- O ptimisation , iyi haber şu ki, bunu yapmak için araçlar, ilk elden bilgi ve pratik problem çözme deneyiminin bir tabanı var ve daha da büyüyor)

S : Performans açısından sağlanan çözümlerle nasıl kıyaslanıyorlar ?

Performans nefes kesici - QUBO tarafından formüle edilen problemin O(1)sabit bir zaman içinde ( [TIME]-Domain içinde) umut verici (!) Bir çözücüsü var ve -Domain'de biraz kısıtlandı [SPACE](yakın zamanda açıklanan LLNL hilelerinin bu fiziksel dünyadan kaçınmasına yardımcı olabilir, mevcut QPU uygulaması, problemin kısıtlanması boyutları).


Bu ilginç bir cevap, ama noktayı kaçırıyor gibi görünüyor - OP tek bir tane değil, birden fazla küçük model eğitiyor. Dolayısıyla, temel gözleminiz çoğunlukla önemsizdir.
user10938362

@ user10938362 Hak talebinde bulunduğunuz mülkünüz ( küçük modelleri eğitme ), yukarıda belirtilen büyük O-metrik işleme maliyetleri metriğinden nasıl farklıdır ? Tabii birçok küçük modeller bir teorik sadece doğrusal artan toplamı söz (hala) bireyin büyük-O maliyetleri (N şimdi daha küçük, ancak diğer faktörler) işleme, iyisi, bu her bir müthiş daha pahalı toplamı eklemek zorunda hem Kurulum hem de Sonlandırma genel gider maliyetlerinin ek maliyetleri ve tüm eklenti Genel gider maliyetleri (parametreler / veriler / sonuçlar + genellikle her adımda SER / DES işleme maliyeti çiftleri)
user3666197

0

Bu bir cevap değil, ama ...

Eğer koşarsan

df.groupby(['measurement_id', 'time', 'group']).apply(
    lambda x: cluster(x['var'], x['object']))

(yani, yalnızca Pandalar ile), zaten birkaç çekirdek kullandığınızı göreceksiniz. Bunun nedeni sklearn, joblibvarsayılan olarak çalışmayı paralel hale getirmek için kullanılmasıdır. Sen edebilirsiniz DASK'ın lehine zamanlayıcı aktarır ve belki parçacıkları arasında veri paylaşımı üzerinde daha fazla verim almak, ancak bu kadar uzun yaptığınız çalışmalarda olarak CPU bağımlı böyle, bunu hızlandırmak için yapabileceği bir şey yoktur olacaktır.

Kısacası, bu bir algoritma problemidir: hesaplamak için farklı çerçeveler düşünmeye çalışmadan önce gerçekten hesaplamanız gereken şeyleri bulun.


Eğer açıklayabilir misiniz neden söz yok "arasında veri paylaşımı ... parçacığı ..." düzenlediği iş bölünmüş bir kez joblib-spawned süreçler , iş parçacığı ile ilgisi olduğuna göre daha az paylaşımı ile? Argümanları açıkladığın için teşekkür ederim.
user3666197

Tam olarak, jboblib normalde süreçleri kullanır, ancak alternatif olarak dask'ı arka uç olarak kullanabilir, burada iplik ve süreç karışımınızı seçebilirsiniz.
mdurant

Ben paralel bilgi işlem için bir yeniyim, ama sklearn paralelleştirme kullanıyor olsa bile, bu ayarlarda işe yaramaz mı? Yani, her kümeleme işlemi sadece 10 noktaya uygulandığı için sklearn tarafından gerçekleştirilen işlemler son derece basittir. Yine, burada yanılmış olabilirim, ama orijinal veri parçalarını işlemeye nasıl paralel yaptığımızın asıl sorun olduğunu düşünüyorum.
Kuba_

"bu ayarlarda işe yaramaz" - 1 yerine 8 CPU çekirdeği değerinde performans kullanıyorsunuz
mdurant

0

Ben bir uzman değilim Dask, ama bir temel olarak aşağıdaki kodu sağlar:

import dask.dataframe as ddf

df = ddf.from_pandas(df, npartitions=4) # My PC has 4 cores

task = df.groupby(["measurement_id", "time", "group"]).apply(
    lambda x: cluster(x["var"], x["object"]),
    meta=pd.Series(np.nan, index=pd.Series([0, 1, 1, 1])),
)

res = task.compute()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.