sobota, 27 czerwca 2015

Introduction to Big Data with Apache Spark - Week 4 and Week 5 - i czy potrzebne są certyfikaty

Kurs jest oficjalnie zakończony. Ostatnie dwa tygodnie w końcu wzniosły się ponad mechaniczne przetasowywanie zbiorów RDD i było kilka problemów, które można już określić mianem "inteligentnych".

Zanim jednak do tego przejdziemy i zanim zobaczymy jakikolwiek kod - kwestia certyfikatów - a w zasadzie rozmów o certyfikatach...

Toksyczny monopol na ocenianie i dlaczego "lans" to twoja tarcza nadzei

Certyfikaty to czasem temat groteskowy - rozdawane są po jednodniowych "szkoleniach miękkich" gdzie uczestnicy rysowali koła na tablicy i udawali zwierzęta. Certyfikat dostaje każdy kto wysiedzi 8 godzin (a czasem nawet ci, którzy nigdy tam nie było). Ktoś kto szczyci się takim dokumentem ryzykuje wystawienie sam siebie na z deczka ośmiesznie.

Inna para kaloszy to czasem nie pozbawione podstaw wątpliwości czy za certyfikatem naprawdę stoi wiedza i jeśli stoi to czemu zasłaniasz się certyfiaktem? Do tego jeszcze wrócimy bo jak to w życiu inżyniera "to zależy" - więc najpierw druga strona medalu:

Ludzie rozmawiający na dany temat

Generalnie koncept klucz w tej sprawie to : "Ludzie, którzy potrafią rozmawiać na dany temat".

O co dokładnie chodzi? Najpierw przykład własny.Dawno dawno temu gdy filmy trzymało się na płytach CD a ze stron atakowały animowane gify (a strony oglądało się w kafejkach bo nikt nie miał wtedy jeszcze internetu) - byłem "hakerem" - wysłałem kilka anonimowych maili przez telnet oraz poinstalowałem netbusa pod windows 95 ludziom na pracowni aby wyświetlić im na pulpicie zdjęcia gołych lasek akurat gdy przechodził nauczyciel.

To stadium jest doskonale zdefiniowane i nazywa się --> https://pl.wikipedia.org/wiki/Script_kiddie. Pamiętam, że używaliśmy takich słów jak "exploit" czy "socjotechnika". Przychodziliśmy do wspomnianych kafejek i zgrywaliśmy skrypty, które coś tam robiły. Z tego co wiem kafejki miały obrazy windows i po każdej nocy wgrywały system na nowo bo to było szybsze niż usuwanie wszystkich wirusów.Rozmawialiśmy o tych skryptach, i tam były jakieś  żargony, których nie pamiętam i być może dla niektórych naprawdę brzmieliśmy jak hakerzy.

Generlanei byliśmy dupa a nie hakerzy ale umieliśmy rozmawiać o "hakowaniu".

Podobnie można umieć rozmawiać o innym dowolnym temacie - wybierzmy coś sobie http://www.pocket-lint.com/news/132235-tech-jargon-for-2015-an-a-to-z-of-the-new-buzzwords-to-learn-this-year .

Nie licząc epickiego źródła buzzwordów jakim stał się Agile to chyba ostatnio bardzo popularne może być słowo "Cloud".

Ludzie rozmawiający o "chmurze"

Pamiętam jeszcze na początku 2013 jadąc samochodem słuchałęm 5 minutowy wywiad jakiejś babki opisującej windows azure i przez całe 5 minut w zasadzie przewijały się słowa "chmura","efektywnosć","skalowanie" ," jeszcze raz efektywnosć" , "data center", "wyzwania" i na koniec "efektywność".

Ona naprawdę umiała "rozmawiać o chmurze".

I teraz ktoś kto ma dużo pieniędzy a nie ma wiedzy technicznej może słuchać takiej osoby i dojść do wniosku "brzmi jakby się znała". Wyśle drugą osobę operującą podobnym zestawem słów i oni się wzajemnie dogadują bez głębszego wnikania o co tak naprawdę chodzi. W końcu gdzieś musi pojawić się jakiś człowiek, który będzie wiedział o co w tym wszystkim chodzi. ALE....

Na arenę wchodzi nauka o nazwie Kognitywistyka, która niesie ze sobą dosyć smutne wieści - otóż ludzie nie oceniają innych zbyt obiektywnie, mamy tzw. zmysły i one nie działają tak jak myślimy - w skutek czego osoba, która uzna za rozmowę osób które "rozmawiają o X" za bełkot może sprawić tzw "negatywne wrażenie" jeśli nieopacznie da upust swojej frustracji lub nieodpowiedzialnie będzie chciała ukazać rzeczy takimi jakie są....

A jest taki certyfikat, papier na stół, nerwów mniej bo z założenia ten papier udowadnia umiejętność "rozmawiania o" a osoby, które "rozmawiają o" zazwyczaj nie posiadają odpowiedniej wiedzy by określić istotę wiedzy stojąca za certyfikatem.

Ludzie którzy robią

Czyli certyfikat pomaga tak? No niekoniecznie bo teraz zaczyna się ciekawa gra. Co gdy po drugiej stronie jest jednak osoba, która rozumie. Ponieważ ona "ogólnie rozumie" wiec rozumie też, że certyfikat oznacza kombinację "pewnej teorii+skońćzonej liczby podejsć do egzaminu".

Teoria jest bardzo potrzebna i moim zdaniem jest niezbędnym uzupełnieniem praktyki ale sama teoria bez praktyki nie wystawi nas na obcowanie z takim kodem jak poniżej - (uwaga długie)

 def savePartition(
        url: String,
        table: String,
        iterator: Iterator[Row],
        rddSchema: StructType,
        nullTypes: Array[Int],
        properties: Properties): Iterator[Byte] = {
      val conn = DriverManager.getConnection(url, properties)
      var committed = false
      try {
        conn.setAutoCommit(false) // Everything in the same db transaction.
        val stmt = insertStatement(conn, table, rddSchema)
        try {
          while (iterator.hasNext) {
            val row = iterator.next()
            val numFields = rddSchema.fields.length
            var i = 0
            while (i < numFields) {
              if (row.isNullAt(i)) {
                stmt.setNull(i + 1, nullTypes(i))
              } else {
                rddSchema.fields(i).dataType match {
                  case IntegerType => stmt.setInt(i + 1, row.getInt(i))
                  case LongType => stmt.setLong(i + 1, row.getLong(i))
                  case DoubleType => stmt.setDouble(i + 1, row.getDouble(i))
                  case FloatType => stmt.setFloat(i + 1, row.getFloat(i))
                  case ShortType => stmt.setInt(i + 1, row.getShort(i))
                  case ByteType => stmt.setInt(i + 1, row.getByte(i))
                  case BooleanType => stmt.setBoolean(i + 1, row.getBoolean(i))
                  case StringType => stmt.setString(i + 1, row.getString(i))
                  case BinaryType => stmt.setBytes(i + 1, row.getAs[Array[Byte]](i))
                  case TimestampType => stmt.setTimestamp(i + 1, row.getAs[java.sql.Timestamp](i))
                  case DateType => stmt.setDate(i + 1, row.getAs[java.sql.Date](i))
                  case DecimalType.Unlimited => stmt.setBigDecimal(i + 1,
                      row.getAs[java.math.BigDecimal](i))
                  case _ => throw new IllegalArgumentException(
                      s"Can't translate non-null value for field $i")
                }
              }
              i = i + 1
            }
            stmt.executeUpdate()
          }
        } finally {
          stmt.close()
        }
        conn.commit()
        committed = true
      } finally {
        if (!committed) {
          // The stage must fail.  We got here through an exception path, so
          // let the exception through unless rollback() or close() want to
          // tell the user about another problem.
          conn.rollback()
          conn.close()
        } else {
          // The stage must succeed.  We cannot propagate any exception close() might throw.
          try {
            conn.close()
          } catch {
            case e: Exception => logWarning("Transaction succeeded, but closing failed", e)
          }
        }
      }
      Array[Byte]().iterator
    }
Jest to kawałek kodu sparka zapisujący dane do bazy. Trzeba było sprawdzić co się tam dzieje bo w pracy nie działało to jak powinno.

I teraz jak ktoś bardzo chwali się certyfikatem a osoba po drugiej stronie jest kumata to może pomyśleć "czy ty naprawdę nie reprezentujesz sobą nic lepszego, że chwalisz się certyfikatami?" To tak jak wpadać do klubu i chwalić się przy barze, że w październiku ktoś wchodzi w drugi próg podatkowy.

Oczywiście można tak to zaaranżować, ze np. niby wyciągając z kieszeni zdjęcia z wycieczki do głodujacych dzieci w afryce wypadną przypadkowo z tej samej kieszeni kluczyki do mercedesa ale generalnie lepszym podejściem wydaje się : "don't try to cheat the system son!" - w sensie uwolnij się z myślenia magicznej pigułki które gloryfikuje osiąganie celów najmniejszym wysiłkiem (tak wiem że użyłem korposłowa słowa "cel").

O co chodzi? Np. można robić kurs online i naprawdę łatwo oszukać by go zaliczyć szukając odpowiedzi tu i tam ale gdyby tak jednak się przyłożyć i wartością była zdobyta wiedza a certyfikat pojawia się na chwilę w tle gdy z tego a nie innego powodu ktoś akurat potrzebuje jakiegoś udokumentowania wiedzy, która jest bądź co bądź "efemeryczna" (czyli niefizyczna)?

Dygresja

A z drugiej strony się zastanawiam czy nie zostać konsultantem zarządzania - wpadnę wyliczę, ze mówienie do siebie per team, stawanie w kole zamiast w rąbie i kolorowanie tasków an czerwono zwiększy "efektywność" o 23% i pojadę sobie za zarobione pieniądze w góry stołowe.

Ludzie zniszczeni przez system

Do głowy przychodzi mi jeszcze jedna kategoria - Ludzie zniszczeni przez system. Oni rozumieją czym są certyfikaty ...i próbowali to kiedyś wytłumaczyć ...i dostali 220 prosto w jaja...i się przewrócili na minę... i teraz mają po prostu napisane "zatrudnić 3 risorsy z certyfikatem w wkrecaniu żarówek" ...i chcą to zrobić ...i chcą już iść do domu... i walić wódę... i płakać. Nie ma co z góry osądzać ludzi.

Patrzysz nie w tę stronę

Może zamiast patrzeć na zewnątrz i szukać odpowiedzi na pytanie "kim być dla innych" zadaj sobie pytanie "kim być dla siebie"? Lubisz robić certyfikaty to je rób, nie lubisz to nie rób - to nie atakuje niczyjej strefy osobistej czy jak to się nazywa to pierdol co kto o tobie myśli w tym temacie. Masa osób dogorywa na fejsbuku dokarmiając się lajkami i udając życie w grach komputerowych także jak zdobywanie odznak motywuje cię do nauki - rób to!!!

Także tu jest mój certyfikat:
Tyle że to nie certyfikat a wyniki ćwiczeń bo certyfikat wydrukują za tydzień jak się kurs skończy - a jak nie wydrukują to go sobie sam anrysuję - BO TAK MI SIĘ CHCE!


Dygresja

czy uczyć się dla ocen czy dla wiedzy, oczywiście, ze ku*wa dla wiedzy ale wasz mózg jest tak skonstruowany, że jak będziecie się uczyli dla wiedzy a przy okazji chwalili ocenami to teoretycznie mechanizm nagrody w waszym mózgu wybierze dalszą nauke zamiast strzałów dopaminy za lajki na fejsie po wklejeniu jakiegoś obrazka z demotywatorów

Ten ma aż cztery certyfikaty :

A teraz coś z sensem - week 4

Było to :https://pl.wikipedia.org/wiki/TFIDF . Generalnie czas zainwestowany swego czasu w mahout --> http://pawelwlodarski.blogspot.com/2013/01/mahout-machine-learning-nie-tylko-dla.html bardzo się przydał by to zrozumieć. Jednak opłacało się uczyć czegoś innego aniżeli tylko kolejnych narzędzi do rysowania HTML.

  • TF - znajdź słowa powtarzające się najczęściej w całym zbiorze (tzw korpusie) dokumentów
  • IDF - znajdź słowa, które pojawiają się często w danym dokumencie ale rzadko w innych - będą to słowa specjalistyczne
  • TFIDF - połącz jedno z drugim
Później ciekawe podejście - reprezentacja tekstu jako wektora. Np mamy N tweetów i możemy sobie porównać jak bardzo np. tweet jest podobny do danego dokumentu. I jeszcze jeden mądry link jak to zrobić : https://en.wikipedia.org/wiki/Cosine_similarity

Przekaz do młodzieży generlanie opłaca się uczyć matematyki - szkoda, ze za moich czasów prowadzący nie do końca rozumieli, że to oni są dla nas a nie my dla nich.

week 5

Tutaj było już machine learning profeska - tworzy się model i go trenowało. Nie wszystko zrozumiałem za pierwszym razem ale zaczyna się teraz nowy kurs https://www.edx.org/course/scalable-machine-learning-uc-berkeleyx-cs190-1x także nauka trwa.

Generalnie zasada jest prostsza niż się wydaje : "Stefan lajkował Polską Partię Przyjaciół Piwa i podobnie zrobić Zdzisław. Stefan zalajkował hodowle jedwabników poprzez podobieństwo jest duża szansa, że i Zdzisław tak zrobi." - ciekawe czasy nastały gdzie każdy chce być unikalny i ta unikalność tworzy łatwe do przewidzenia masowe zbiory zachowań.

Scala a python

Python

>>> krotka=("raz",2)
>>> (zm1,zm2)=krotka
>>> zm1
'raz'
>>> zm2
2
>>> 

Scala

scala> val krotka=("raz",2)
krotka: (String, Int) = (raz,2)

scala> val (zm1,zm2)=krotka
zm1: String = raz
zm2: Int = 2

Im więcej języków poznaję tym bardziej mam wrażenie, że dużo łatwiej nauczyć się scali znając cokolwiek innego niż Javę

środa, 17 czerwca 2015

Introduction to Big Data with Apache Spark - Week 3

Tematem obecnego tygodnia obecnego tygodnia było to co każdy powtarza sobie przed rozmową kwalifikacyjną czyli left i right joiny. Oczywiście całość na nowych, przebojowych i rewolucyjnych dataframe (datafrejmach,dataframeach,dataframesach?)

Laborki miały raczej mało wspólnego z wykładem bo zadaniem była analiza logów NASA przy pomocy RDD.

Same joiny są lepsze (chyba) od tych znanych z bazy danych bo zamiast nulli dostajemy Some i None

//Dane
scala> val data1=List((1,"a"),(2,"b"))
scala> val data2=List((1,"c"),(3,"d"))

//rdd
scala> val rdd1=sc.parallelize(data1)
rdd1: org.apache.spark.rdd.RDD[(Int, String)] = ParallelCollectionRDD[0] at parallelize at <console>:23


scala> val rdd2=sc.parallelize(data2)
rdd2: org.apache.spark.rdd.RDD[(Int, String)] = ParallelCollectionRDD[1] at parallelize at <console>:23


//inner join
rdd1.join(rdd2).collect()
res2: Array[(Int, (String, String))] = Array((1,(a,c)))

//left outer join
scala> rdd1.leftOuterJoin(rdd2).collect()
res4: Array[(Int, (String, Option[String]))] = Array((1,(a,Some(c))), (2,(b,None)))

//right outer join
scala> rdd1.rightOuterJoin(rdd2).collect()
res3: Array[(Int, (Option[String], String))] = Array((1,(Some(a),c)), (3,(None,d)))

https://spark.apache.org/docs/latest/api/scala/#org.apache.spark.rdd.PairRDDFunctions

Poprzednie tygodnie

Tutaj linki do poprzednich tygodni - podobno można jeszcze zacząć :

Uwagi i Wnioski

Pytanie czy zrobić to w formie suchych faktów czy ciekawego opowiadania - ciekawe opowiadanie jest ciekawe ale fakty są suche a podobno ma padać cały tydzień także :.

  • To jest dobra strona do obadania operacji na RDD, który przechowuje (klucz, wartość) => Key-Value RDD
  • Odczytywanie plików binarnych jest znacznie szybsze niż plików tekstowych - a scala jest generalnie szybsza od Pythona. I tu nie chodzi o to żeby coś hejtować ale według obrazka no generlanie jest szybsza :
  • Jest taki zajebisty algorytm kompresji - https://en.wikipedia.org/wiki/LZ4_(compression_algorithm)
  • I ten LZ4 jest taki dobry, że jeszcze jeden link : https://code.google.com/p/lz4/

I taki bonus. Można zarejestrować własna funkcję, która zrobi jakieś customowe operacje na DataFrame :

val isEmployeFun = bcEmployees.value contains _

val isEmployee: UserDefinedFunction = sqlContext.udf.register("isEmployee", isEmployeFun)

val filtered = ordered.filter(isEmployee($"login"))


I od razu drugi bonus - co to jest bcEmployees? To średnio czytelnie nazwana zmienna z ćwiczenia ale zmienna(a w zasadzie stała) nie zwyczajna gdyż rozdystrybuowana
val bcEmployees = sc.broadcast(employees)

//a ten jednolinijkowiec to efekt lektury "functional programming in scala" 
//- tak, niektorych ludzi może zabić ale to tylko ćwiczenie
val isEmployeFun = bcEmployees.value contains _

Laborki

Na laborkach trzeba było nauczyć się regular expressions - podejście numer 269.

val pattern="""^(\S+) (\S+)""".r
val log="127.0.0.1 /GET"
pattern findAllIn log next

Performance

Zestaw suchych faktów na tydzień bieżący :

W zasadzie zawsze kiedy jest RDD typu (klucz,wartość) trzeba używać reduceByKey - wtedy mnie szuflowania po kablu jest.

A jak sie kilka razy używa jakiegoś RDD to trzba robić cache()

Ciekawe błędy

It appears that you are attempting to broadcast an RDD or reference an RDD from an action or transformation. RDD transformations and actions can only be invoked by the driver, not inside of other transformations; for example, rdd1.map(lambda x: rdd2.values.count() * x) is invalid because the values transformation and count action cannot be performed inside of the rdd1.map transformation. For more information, see SPARK-5063. - tutaj błąd polegał na tym, ze użyłem rdd.map(coś_tam_od_rdd) - a to co jest w map jest wysyłąne do workerów - czyli ogólnie bez sensu.

Testy przechodziły, ale po submicie zadania : Timeout error happened during grading. Please review your code to be more efficient and submit the code again.
Co tu można było zrobić :

  • Generalnie chodzi o to aby używać specjalizowanych funkcji zamiast tych bardziej ogólnych co (znowu chyba) da Sparkowi hinta, które dane szufffffeling.
  • reduceByKeys,sortByKeys,mapValues
  • A jak się robi groupBy a później reduce to zazwyczaj jest to suboptymalne (tego nauczyłem się kiedyś w korpo - jak ktoś zjebie to mówi "we have reached a suboptimal state")

czwartek, 11 czerwca 2015

Introduction to Big Data with Apache Spark - Week 2

Tydzień pierwszy opisany tutaj ~~~~> http://pawelwlodarski.blogspot.com/2015/06/introduction-to-big-data-with-apache.html

W końcu pojawiła się jakaś definicja BigData, którą rozumiem. BigData to nie jest wtedy jak ma się XBajtów ale wtedy jak "Ilość danych rośnie szybciej niż zdolność obliczeniowa jednostki"

Lekcja 3 - jak powstał spark

Grupa naukowców pracowała z hadoopem i zaczęła się zastanawiać dlaczego każda iteracja w pętli for zapisuje wynik na dysku sieciowym. Po chwili doszli do wniosku, ze skoro są profesorami to napiszą coś fajnego, wzięli scalę, tez stworzoną i przez profesora i zrobili prawdziwie profesorskie narzędzie.

Spark ma zastąpić hadoopa ale i tak książka "Hadoop in action jest planowana na przełom tego roku" - (mam nadzieję, że to nie będzie utopione 37 złotych.)

Papiery naukowe,Prace naukowe, white papers...

W kursie znalazły się dwa linki do prac naukowych o Sparku i RDD. Fajnie poczytać czasem prace naukowe gdyż są dokładne i ciekawe.

Link pierwszy : http://usenix.org/system/files/conference/nsdi12/nsdi12-final138.pdf

Opisuje RDD jako takie

  • Spark przy algorytmach iteracyjnych działa trzynaście trylionów razy szybciej niż hadoop
  • Jest opisane jak dokładnie działa RDD, że jest lazy i co to daje, że łatwo odtworzyć w razie awarii i co to daje

Pierwszy cytat :

"Spark is up to 20× faster than Hadoop for iterative applications, speeds up a real-world data analytics report by 40×, and can be used interactively to scan a 1 TB dataset with 5–7s latency"

"Finally, users can control two other aspects of RDDs: persistence and partitioning."

I chyba w tym momencie zrozumiałem ogromną zaletę tego narzędzia.

"Users can indicate which RDDs they will reuse and choose a storage strategy for them (e.g., in-memory storage). They can also ask that an RDD’s elements be partitioned across machines based on a key in each record. This is useful for placement optimizations, such as ensuring that two datasets that will be joined together are hash-partitioned in the same way."

Link drugi : http://people.csail.mit.edu/matei/papers/2010/hotcloud_spark.pdf

Opisuje Sparka jako implementację RDD.

"We have implemented Spark in about 14,000 lines of Scala."

First law of software quality: e=mc^2, errors = (more code)^2 - wiele osób błędnie chwali się, że ich projekt jest wielki (to akurat prawda ale sami są tego winni) i przez to "bardziej profesjonalny" - tak jak bardziej kręte drogi są bardzo profesjonalne.

""The cache action leaves the dataset lazy, but hints that it should be kept in memory after the first time it is computed, because it will be reused"

"The save action evaluates the dataset and writes it to a distributed filesystem such as HDFS. The saved version is used in future operations on it"

A te dwa były o tym, że spark jest lazy i jak to tam działa.

Komunikacja master<--> worker

Są dwa Fajne typy zmiennych :

Broadcast variables

Z tego co zrozumiałem funkcje operujące na RDD są za każdym razem wysyłane do workera i czasem jakaś zmienna może się zaplątać w closure. A ten tutaj wynalazek sprawia, że zostanie wysłana raz tylko jeden.
val broadcastVar=sc.broadcast(7)
broadcastVar: org.apache.spark.broadcast.Broadcast[Int] = Broadcast(12)

scala> val rdd=sc.parallelize(Seq(1,2,3,4))
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:21


scala> rdd.map(_+1).collect
res16: Array[Int] = Array(2, 3, 4, 5)


scala> rdd.map(_+broadcastVar.value).collect
res18: Array[Int] = Array(8, 9, 10, 11)

Accumulators

O ile lambda leci w kierunku driver --> worker to accumulator lecu worker --> driver. Albo inaczej worker to widzi jako write-only a driver jako read-only.
scala> val acc=sc.accumulator(0)
acc: org.apache.spark.Accumulator[Int] = 0

scala> rdd.foreach(acc+=_)

scala> acc.value
res20: Int = 10
I ponieważ transformacje mogą być wykonywane wielokrotnie bo albo coś padnie albo działa za wolno - to akumulatorów tam nie można stosować - jedynie w akcjach.

Kiedy keszować

val lines=sc.textFile
val filtered=lines.filter()
lines.count()
filtered.count()

I powyżej lines będzie ewaluowane dwa razy - ale w przykładzie poniżej już nie!:

val lines=sc.textFile
lines.cache
val filtered=lines.filter()
lines.count()
filtered.count()

Code quality

I tutaj taka ciekawa rzecz :

# Define a function to filter a single value
def ten(value):
    if (value < 10):
        return True
    else:
        return False
# The ten function could also be written concisely as: def ten(value): return value < 10

# Pass the function ten to the filter transformation
# Filter is a transformation so no tasks are run
filteredRDD = subRDD.filter(ten)
To jest kod z przykładów na kursie. I to jest bez sensu bo if(cond) true else false można zwyczajnie zastąpić cond - no to widać, ze profesor nie profesor - sonara trzeba włączyć (chociaż pewnie i tak dali do przygotowania te ćwiczenia jakiemuś laborantowi)

Laborki

Bardzo proszą aby nie publikować zadań to nie będę. Takie ciekawe fakty tylko

  • SPARK UI - http://localhost:4040/jobs/
  • http://localhost:4040/storage/ - tutaj widać wszystkie keszowane i persistowane rdd

Można nazywać sobie RDD by było łatwiej skumać w logach co się dzieje

scala> rdd.setName("zbior ku*wa")
res28: rdd.type = zbior ku*wa ParallelCollectionRDD[0] at parallelize at <console>:21

scala> rdd.toDebugString
res30: String = 
(1) zbior ku*wa ParallelCollectionRDD[0] at parallelize at <console>:21 [Memory Deserialized 1x Replicated]
 |       CachedPartitions: 1; MemorySize: 96.0 B; TachyonSize: 0.0 B; DiskSize: 0.0 B

Pattern Matching na tupla w Pythonie

Można tak :

In [3]: tup=(1,'a')
lam=lambda (x,y): y
In [8]: lam(tup)
Out[8]: 'a'

czwartek, 4 czerwca 2015

Introduction to Big Data with Apache Spark - Week 1

Jeśli ktoś jeszcze nie zauważył to na edx.org rozpoczął się właśnie kurs : "BerkeleyX: CS100.1x Introduction to Big Data with Apache Spark". W kursie używają głównie pythona a ja tutaj postaram się opisać jak można chociaż część ćwiczeń zrobić w scali.

W trakcie pierwszego tygodnia poza ćwiczeniami było trochę o profilach osób mieniących się "Data Scientist" jak i "Data Engineer" i cóż ci ludzie robią. Część praktyczna na razie polegała na instalacji virtualboxa i vagranta - a następnie odpaleniu kilku prostych przykładów sparka na gotowym obrazie. Na forum 90% pytań to problemy posiadaczy windowsa z instalacją obydwu wspomnianych narzędzi. Pomyślałem sobie, że to fajnie iż robię te ćwiczenia na linuxie - potem zdałem sobie sprawę, że 40 godzin w tygodniu pracuję na windowsie, usiadłem i zacząłem płakać...choć nie, nie zacząłem bo od razu przeszedłem do robienia ćwiczeń.

Najpierw teoria - Lekcja 1

Opisywanie tego co się usłyszało w celu zrelacjonowania tego dalej to dobry sposób by informacje zwyczajnie nie przeleciały przez głowę i upadły po drugiej stronie na podłogę.

Najpierw było kilka ciekawych rzeczy odnośnie interpretacji danych a konkretniej błędów przy tejże czynności popełnianych - i jest jedna fajna życiowa rzecz, która doczekała się nawet swojej strony na wiki - http://en.wikipedia.org/wiki/Correlation_does_not_imply_causation

To jest tak zabawny efekt, ze jeszcze jeden obrazek z netu :
I Dilbert - a jak jest dilbert to wiadomo, ze zaraz będzie coś o korpo :

Na kursie był wspomniany przykład badania Seven Countries Study - które zrodziło mit o powiązaniu ilość spożywanego tłuszczu z prawdopodobieństwem ataku serca. W linku można sobie poczytać o badaniu i krytyce oraz zapamiętać by ograniczyć spożycie cukrów prostych.

Są dwa zabawne przypadki o których słyszałem w kontekście tego efektu - pierwszy to pozorna zależność pomiędzy zamieszkaniem w okolicy linii wysokiego napięcia a śmiertelnością. Generalnie to działa na wyobraźnię bo prąd, magnetyzm i ciało ludzkie itd, no i liczby nie kłamią przecież - liczby nie kłamią ale ludzi ich nie rozumieją - bo co się okazało. Po dalszych badaniach wyszło na jaw, ze generalnie ludzie nie chcą mieszkać w okolicy linii wysokiego napięcia i działki są tam tańsze, i kupują je biedniejsi ludzie, którzy żyją mniej zdrowiej niż średnia populacji, i większe jest wśród nich umieralność...

Zaś drugi przykład jest związany z czymś coś co się nazywa "regresja do średniej" i tutaj dwa linki

To był dosyć ciekawy przykład z książki Thinking fast and slow albo z Black Swan. Był tam opisany przypadek Kapitana lotnictwa, który zauważył, ze zawsze gdy skuteczność pilotów spada i dostaną opierdol to się poprawia. Natomiast gdy jest dobrze i dostaną pochwałę to się pogarsza. No to przestał ich chwalić i tylko opierdalał. I coś w dłuższym okresie czasu morale siadło.

Kahneman próbował im wytłumaczyć, że skuteczność po doskonałych dniach by się pogarszała tak czy inaczej nawet bez pochwał a poprawiała bo bardzo słabych dniach nawet bez opierdolu. Nie dochodziło to do kapitana, więc zrobili pewien eksperyment. Narysowali kółko i kazali rzucać kapitanowi monetami doń tak by wycelować najbliżej środka. Zrobili dwa warianty - jeden z opierdalaniem a drugi bez - dużej różnicy nie było. To w sumie tak jakby opierdolić generator Radom.nextInt jak wygeneruje mała liczbę i pokazywać palcem, że podziałało jak wygeneruje za chwilę dużą liczbę.

Niebezpieczeństwo

Jeszcze gorsze od olewania liczb jest fanatyczna w nie wiara bez uwzględniania kontekstu ludzkiego - tzw technokracja. Kolega kolegi opowiadał o przypadkach, gdzie ludzie wydawali osądy wyssanez palca na podstawie liczenia średniej ważonej z burndown charta - programiści szybko się do tego dostosowują i potrafią kosztem produktywności (i co gorsza kosztem kultury pragmatyzmu) wygenerować odpowiedni wykres dla managerów. Ci którzy starają się kulturalnie zwrócić uwagę, ze to bez sensu i ogólnie firma na tym traci a zyskuje jedynie manager dostają etykiete kłótliwych -, że tak podobno jest powiedział mi kolega kolegi od strony stryjka.

Hippo

Czyli “HiPPO”—the highest-paid person’s opinion", a "highest-paid person’s" to ta osoba od której wymagane jest zgadywanie odnośnie przyszłości - tak twierdzą autorzy kursu jakkolwiek nie używają słowa "dupy" ani "stzrelanie".

Google jako wyrocznia

Naukowcy z Princeton dokonali analizy zapytań z google i stwierdzili, ze do 2020 nikt nie będzie używał już facebooka gdyż podobny trend zdążył się w przypadku myspace. Naukowcy z facebooka dokonali analizy danych z googla i stwierdzili, ze do 2020 nie będzie Princeton - ale to nie jest najstraszniejsze. Według tej samej procedury badawczej do 2060 nie będzie na ziemi powietrza!!

I fajny link jeszcze :
Fajny Link

lesson 2

Było o tym, ze dane trzeba przygotować, przefiltrować, że rzeczywistość dookoła nam nie będzie ładnie podawać informacji ale trzeba będzie je oszlifować i bez odpowiedniej technologii się zer.. nie uda się.

Było o Data Science i, że ludzie się ogólnie do tego nie nadają - "It is human nature to make assumptions ", "Humans have biases based on prior observations"

Dobra pogadali a teraz konkrety L

PROGRAMOWANIE

Generalnie polecam "Spark in action" nawet jak to jest Meap na razie bo tam jest konkretna praktyka z instalacją i komendami na linuxie. A jak fajnie, że ja mam linuxa...chociaż zaraz...

Najpierw byłą instalacja VirtualBoxa i Vagranta - zajebisty zestaw na prowadzenie warsztatów, trzeba będzie wypadać przy okazji. I od razu nauczka - na stronie downloadu są dwie opcje "i386" i "amd64" - i wcale nie jest tak, że ta pierwsza to intel a druga amd tylko pierwsza to 32bity a druga 64bity - czasem jednak warto czytać instrukcje bo jak odinstalowałem virtualboxa 32 bitowego to było późno i chyba za dużo komend ze strony przekleiłem bo przy okazji odinstalwoałem sobie Unity i zrobiło się jeszcze później.

W każdym razie po instalacji vagranta idzie "vagrant up" - zaciąga się obraz i możemy odpalić taki notebook, w którym można pisać w pythonie. Ale przecież chcielibyśmy też popisać w scali.

Popisać w scali

Wbijamy na spark REPL :
vagrant ssh
echo $SPARK_HOME // tak dowiemy sie gdzie jest spark
///usr/local/bin/spark-1.3.1-bin-hadoop2.6
cd /usr/local/bin/spark-1.3.1-bin-hadoop2.6
bin/spark-shell

//i mamy scalę !
//Using Scala version 2.10.4 (OpenJDK Client VM, Java 1.7.0_79)

Dziś przyjmiemy inną taktykę i zamiast śmiać się z innego jezyka - zobaczymy też co ciekawego w Pythonie. Bo jakoś ponoć to język Data Scientistów.

Jest taki repl online - Python : http://www.tutorialspoint.com/ipython_terminal_online.php i tam można sobie poeksperymentować. Na razie nauczyłem się, że (xrange(10)) - to chyba to samo co (0 until 10) w scali.

Python jest bardzo podobny do scali ale nie ma tam val,var i ogólnie typów. W niektórych środowiskach pracy to może być zaleta bo programiści mogą powiedzieć "przynajmniej nasz kod się uruchamia" (to żart oczywiście (chociaż nie, znam miejsca gdzie to nie będzie żartem))

Porównanie przykładów : Python ex1
# Check that Spark is working
largeRange = sc.parallelize(xrange(100000))
reduceTest = largeRange.reduce(lambda a, b: a + b)
filterReduceTest = largeRange.filter(lambda x: x % 7 == 0).sum()

# If the Spark jobs don't work properly these will raise an AssertionError
assert reduceTest == 4999950000
assert filterReduceTest == 714264285
Scala Ex1
val largeRange=sc.parallelize(0L until 100000L)
// largeRange: org.apache.spark.rdd.RDD[Long]

val reduceTest=largeRange.reduce(_+_)
//reduceTest: Long = 4999950000

val filterReduceTest=largeRange.filter(_ % 7==0).sum()
//filterReduceTest: Double = 7.14264285E8
Python ex2
# Check loading data with sc.textFile
import os.path
baseDir = os.path.join('data')
inputPath = os.path.join('cs100', 'lab1', 'shakespeare.txt')
fileName = os.path.join(baseDir, inputPath)

rawData = sc.textFile(fileName)
shakespeareCount = rawData.count()

print shakespeareCount

# If the text file didn't load properly an AssertionError will be raised
assert shakespeareCount == 122395
Scala Ex2
val homeDir=System.getProperty("user.home")
val path = (s"${homeDir}/data/cs100/lab1/shakespeare.txt")
path: String = /home/vagrant/data/cs100/lab1/shakespeare.txt
val rawData=sc.textFile(path)
val shakespeareCount=rawData.count
//shakespeareCount: Long = 122395
Python Ex3
# TEST Compare lists (2b)
# This should print '1 test passed.'
unsortedList = [(5, 'b'), (5, 'a'), (4, 'c'), (3, 'a')]
Test.assertEquals(sorted(unsortedList), [(3, 'a'), (4, 'c'), (5, 'a'), (5, 'b')],
                  'unsortedList does not sort properly')
Scala Ex3
val lista=List((5,'b'),(5,'a'),(4,'c'),(3,'a'))
lista.sorted == List((3,'a'),(4,'c'),(5,'a'),(5,'b'))
res3: Boolean = true

To tyle na pierwszy tydzień odnośnie wyżej wspomnianego kursu.

BONUS

Widać, że spark jest an topie bo hortonworks rzucił też wstęp do tutoriala "Data Science i Spark". Artykuł tutaj : http://hortonworks.com/blog/introduction-to-data-science-with-apache-spark/.

Jedyne ale to to, ze kurs jest przeznaczony dla platformy hortonworks, a że jej nie ma to poniżej dostosowanie ćwiczeń do już posiadanego obrazu vagranta ze sparkiem.

Najpierw jest tam instalacja ciekawej konsolki - https://github.com/apache/incubator-zeppelin ale to an kiedy indziej. Na razie trzeba wtgenerować sobie plik z logami do analizy.

W /usr/local/bin/spark-1.3.1-bin-hadoop2.6 wbijamy do katalogu conf

sudo mv  conf/log4j.properties.template conf/log4j.properties

#wrzucić to do log4j.properties
#file
log4j.rootCategory=INFO, console, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n

# Settings to quiet third party logs that are too verbose
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO

#file
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=/var/log/spark.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n


sudo touch /var/log/spark.log
sudo chown vagrant /var/log/spark.log

Odpalić konsolę sparka ze scalą i jedziemy :

val sparkLogs=sc.textFile("/var/log/spark.log")

import sqlContext.implicits._
import java.text.SimpleDateFormat
import java.sql.Date

case class Log(level:String,date:Date,content:String)
val df=new SimpleDateFormat("yy/mm/dd HH:mm:dd")


val sparkFrame=sparkLogs.map {line =>
val s=line.split(" ")
val date=df.parse(s(0) + " " + s(1))
val logLevel=s(2)
val logContent=s(3)
Log(logLevel,new Date(date.getTime()),logContent)}.toDF()
sparkFrame.registerTempTable("spark")

I tutaj przyda się trochę znajomości REPLa jednak. Do tej pory to olewałem bo były worksheety w IDE. Są dwie dobre strony :

MOTYWACJA: - jednak jak coś jest potrzebne to się tego można nauczyć - tutaj najciekawsze polecenia to : :paste, :paste -raw, :history + :edit

I wio i błąd a na błędach się uczymy:

Caused by: ERROR XBM0H: Directory /usr/local/bin/spark-1.3.1-bin-hadoop2.6/metastore_db cannot be created.
Nie wiem czy poniższe rozwiązanie jest najlepsze bo nie jestem pełnoetatowym adminem :

vagrant@sparkvm:/usr/local/bin/spark-1.3.1-bin-hadoop2.6$ cd ..
vagrant@sparkvm:/usr/local/bin$ sudo chmod 775 spark-1.3.1-bin-hadoop2.6/
sudo chown vagrant spark-1.3.1-bin-hadoop2.6/

Jak już tu jesteśmy to zobaczmy co tam w tym metastore jest :

vagrant@sparkvm:/usr/local/bin/spark-1.3.1-bin-hadoop2.6/metastore_db$ ls -l
total 28
-rw-rw-r-- 1 vagrant vagrant  608 Jun  4 13:55 README_DO_NOT_TOUCH_FILES.txt
-rw-rw-r-- 1 vagrant vagrant   38 Jun  4 13:59 db.lck
-rw-rw-r-- 1 vagrant vagrant    4 Jun  4 13:59 dbex.lck
drwxrwxr-x 2 vagrant vagrant 4096 Jun  4 13:55 log
drwxrwxr-x 2 vagrant vagrant 4096 Jun  4 13:55 seg0
-rw-rw-r-- 1 vagrant vagrant  932 Jun  4 13:55 service.properties
drwxrwxr-x 2 vagrant vagrant 4096 Jun  4 13:59 tmp
vagrant@sparkvm:/usr/local/bin/spark-1.3.1-bin-hadoop2.6/metastore_db$ cat README_DO_NOT_TOUCH_FILES.txt 

# *************************************************************************
# ***              DO NOT TOUCH FILES IN THIS DIRECTORY!                ***
# *** FILES IN THIS DIRECTORY AND SUBDIRECTORIES CONSTITUTE A DERBY     ***
# *** DATABASE, WHICH INCLUDES THE DATA (USER AND SYSTEM) AND THE       ***
# *** FILES NECESSARY FOR DATABASE RECOVERY.                            ***
# *** EDITING, ADDING, OR DELETING ANY OF THESE FILES MAY CAUSE DATA    ***
# *** CORRUPTION AND LEAVE THE DATABASE IN A NON-RECOVERABLE STATE.     ***
# *************************************************************************

Nooo dobra to tyle. Kończymy zabawę w scali.

//TO jest tak lazy , ze dopiero po "show()" się wywala !
sparkFrame.groupBy("level").count().show()

/*
level count
WARN  6    
INFO  64 
*/

sqlContext.sql("SELECT level, count(1) from spark  group by level")
//res6: org.apache.spark.sql.DataFrame = [level: string, _c1: bigint]

sqlContext.sql("SELECT level, count(1) from spark  group by level").show
/*level _c1
WARN  6  
INFO  64 */


import org.apache.spark.sql.Row
 val result = sqlContext.sql("SELECT level, count(1) from spark  group by level").map {
 case Row(level: String, count: Long) => {
      level + "\t" + count
 }
}.collect()

println("%table Log Level\tCount\n" + result.mkString("\n"))
/* %table Log Level Count
WARN 6
INFO 64*/

To jest ciekawe bo DataFrame mówi do programisty "mów mi co trzeba zrobić nie mów jak i nie kontroluj" i wychodzi to lepiej. Czasem też warto zrobić sobie przerwę bo w ferworze pisania zacząłem zmieniać konfigurację log4j tutaj w tekście na blogu i dziwiłem się, że spark nie łyka tej konfiguracji... Czasem można spojrzeć na zieleń w celu uwolnienia umysłu. W poprzedniej pracy mieliśmy kalendarz ze zdjęciem fitneski - takiej miłej i uśmiechniętej, która promowała zdrowy tryb życia. I zawsze to podnosiło kreatywność zespołu ale przyszły korpo służby i kazały zdjąć kalendarz redukując naszą efektywność o 17,3%. Generalnie pomału mam wrażenie, że niektórzy mylnie używają słowa "profesjonalista" do opisu smutnego pana w wyprasowanej smutnej koszuli siedzącego w smutnym koncie smutnego piętra z gołymi i smutnymi ścianami. Ale zresztą ja się tam nie znam.

Za tydzień - lekcje 3 i 4 - ma już się zacząć jakieś datascience to powinno być ciekawie.