niedziela, 16 czerwca 2024

Analiza sentymentów - wpisy na mediach społecznościowych (podział danych)

Ten wpis zaczniemy od stworzenia DataFrame z danymi treningowymi

train_df = pd.read_csv('train.csv', encoding='ISO-8859-1').dropna(subset=['text', 'sentiment'])

Ta linijka kodu pozwala na załadowanie danych z pliku "train.csv" do zbioru danych treningowych train_df. Użyte jest kodowanie znaków "ISO-8859-1", które jest standardem dla języków zachodnioeuropejskich, pozwalającym odczytać i zinterpretować znaki takie jak "é". Dzięki funkcji dropna() pozbywamy się wartości NaN z naszego zbioru danych. Parametr subset określa, które kolumny mają być brane pod uwagę przy usuwaniu braków. Usuwamy braki w kolumnach "text" (zawierającej wpisy na Twitterze) oraz "sentiment" (określającej sentyment). Gdybyśmy nie pozbyli się tych pustych wartości, mogłoby to zaburzyć proces trenowania modelu.

Kolejną linijką kodu jest:

test_df = pd.read_csv('test.csv', encoding='ISO-8859-1').dropna(subset=['text', 'sentiment']) 

Jest to zestawy tych samych operacji tylko, że tym razem odbywają się one na zbiorze testowym "test.csv".

Kolejnym krokiem jest podzielenie zbioru treningowego na dwa zestawy. Jeden z nich będzie zawierał teksty, których sentyment badamy, a drugi wartości wynikowe, które mogą być jedną z trzech możliwości: pozytywny, negatywny lub neutralny.

train_texts = train_df['text'].values
train_labels = train_df['sentiment'].values

To samo zróbmy dla zbioru testowego:

test_texts = test_df['text'].values
test_labels = test_df['sentiment'].values

"text" lub "sentiment" to nazwy kolumn, a właściwość "values" sprawia, że dana kolumna jest konwertowana do tablicy NumPy. Dzięki takiej konwersji dane będą kompatybilne z wymaganiami narzędzi NLP.

Z mapujmy sobie etykiety sentymentów, z określeń w języku naturalnym na liczby.

label_encoder = {'positive':1, 'negative': -1, 'neutral': 0}

"label_encoder" od teraz przechowuje wartości znacznie bardziej przydatne do trenowania modelu. Każde z trzech możliwych oznaczeń sentymentów danej wypowiedzi zostało zakodowane na wartości 1, -1 i 0, to jest istotne z punktu widzenia działania algorytmu.

I tak, mając już etykiety z mapowane można przejść do stworzenia zbioru z danymi wynikowymi (ze zmiennymi zależnymi).

y_train = np.array([label_encoder[label] for label in train_labels])

Metoda "np.array()" tworzy końcową listę etykiet sentymentów, co będzie stanowić zbiór danych do predykcji podczas treningu modelu. Te wartości są tworzone w taki sposób, że "label" sprawdza "train_labels" i jeśli załóżmy pierwszą wartością w train_labels będzie "positive" co będzie etykietą sentymentu, to dzięki słownikowi "label_encoder" do "y_train" zostanie dopisana, w tym przypadku wartość równa 1. "Label_encoder" posiada słownik, w którym "positive" odnosi się do wartości 1. Niech drugim elementem, będzie sentyment opisany jako "neutral", zostanie to odniesione do zawartości "label_encoder" i "y_train" zyska kolejną wartość, w tym wypadku 0, gdyż w zbiorze "label_encoder" jest jasno zapisane, że "neutral" odpowiada wartości 0.

y_test = np.array([label_encoder[label] for label in test_labels])

Analogicznie, robimy to samo co wcześniej, tym razem na danych testowych. W rezultacie tworzymy zbiór danych wynikowych (wartości określających dany sentyment: pozytywny, negatywny lub neutralny dla każdej wartości z "test_labels"), który będzie użyty podczas testowania modelu.

C.d.n... ;-)

Wpis oparty o wiedzę z kursu: Machine Learning Mastery

Analiza sentymentów - wpisy na mediach społecznościowych (ustawianie środowiska)

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

Rozpocznę nową serię wpisów. Projekt ten będzie dotyczył analizy sentymentów treści, które z założenia reprezentują wpisy na mediach społecznościowych, takich jak na przykład Twitter. Model będzie miał na celu ocenę, czy dany tweet ma charakter pozytywny, negatywny czy neutralny.

Użyję do tego zbioru danych, dostępnego na Kaggle: Sentiment Analysis Dataset. Zbiór danych zawiera zbiór treningowy i testowy.

A teraz przejdę do opisu mojego Jupiter Notebook. Najpierw zaczniemy od zaimportowania odpowiednich modułów.

Importując numpy jako np, będziemy mogli dokonywać różnych operacji matematycznych na tablicach danych i macierzach.

Importując pandas jako pd, będziemy mogli manipulować danymi znajdującymi się w Seriach (Series) i w Ramkach Danych (DataFrame).

Importując TfidfVectorizer z modułu sklearn.feature_extraction.text, przekształcimy teksty na macierz cech TF-IDF (Term Frequency-Inverse Document Frequency). Co nam to da? Każde słowo będzie mogło otrzymać wagę, odzwierciedlając jego ważność w całym dokumencie. Znaczenie często używanych słów, takich jak "i" lub "jest", zostanie zredukowane. Teksty zostaną odzwierciedlone w formie wektorowej reprezentacji liczbowej, co umożliwi użycie algorytmów uczenia maszynowego.

Importując train_test_split z modułu sklearn.model_selection, będziemy mogli podzielić dane na zbiór testowy i treningowy. Dzięki temu określimy wydajność naszego modelu, używając danych testowych. Kiedy zauważymy, że model słabo generalizuje na zbiorze testowym, to może znaczyć, że jest przeuczony.

Importując LogisticRegression z modułu sklearn.linear_model, będziemy mogli utworzyć modele regresji logistycznej. Klasyfikuje ona binarnie, ale też wieloklasowo. U nas będzie to pozytywny (positive), negatywny (negative) i neutralny (neutral) sentyment. Przykłady danych są oczywiście dostępne do podejrzenia na stronie Kaggle podanej na samym początku. Regresja logistyczna to przy okazji stosunkowo prosty i wydajny model. Skutecznie radzi sobie z dużymi zbiorami danych w krótkim czasie.

Importując Word2Vec z modułu gensim.models, słowa zostaną zamienione na wektory (embeddingi). Korzyści z użycia: przekształca słowa na wektory, które reprezentują semantyczne znaczenie słów. Słowa o podobnym znaczeniu mają wektory, które są do siebie podobne. Word2Vec jest w stanie uchwycić kontekst, porównując dane teksty z tekstami w ich sąsiedztwie.

Importując accuracy_score z modułu sklearn.metrics, będziemy mogli ocenić skuteczność modelu. Ten sposób oceny modelu jest bardzo prosty i intuicyjny, gdyż pokazuje stosunek poprawnych predykcji do całkowitej liczby predykcji. Nazywamy to dokładnością.

Wpis oparty o wiedzę z kursu: Machine Learning Mastery

środa, 8 maja 2024

EDA: Czyszczenie danych - usuwanie duplikatów, obsługa wartości brakujących

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

1. Usuwanie duplikatów:

Duplikaty danych powinny być usuwane, ponieważ każdy niepotrzebnie powielony rekord wpływa na statystyczne analizy danych. Taki duplikat jest traktowany przez model jako oddzielny, pełnoprawny rekord, co może zakłócić wyniki analizy i zmniejszyć skuteczność modeli.

Nieusunięte duplikaty w zbiorze danych przeznaczonym do trenowania modelu mogą prowadzić do jego przeuczenia. Jeżeli występuje ich nadmiar, model może stracić zdolność do generalizacji i będzie efektywnie klasyfikował tylko te przypadki, które bezpośrednio odpowiadają danym treningowym.

Dodatkowo, usunięcie duplikatów przynosi korzyści w postaci odciążenia zasobów obliczeniowych komputerów lub serwerów używanych do analizy danych.

Poniżej prezentuję kod demonstrujący proces usuwania duplikatów w zbiorze danych. Przykład zawiera prosty DataFrame składający się z trzech wierszy danych, gdzie pierwszy i ostatni wiersz są identyczne. Usunięcie duplikatów pokazuje, jak zmniejsza się liczba wierszy w ramce danych po zastosowaniu metody drop_duplicates(). Co warto wiedzieć, to df.shape[0] zwraca liczbę wierszy, a gdybyśmy użyli df.shape[1], to zwróciłoby nam liczbę kolumn.

import pandas as pd

data = [
    [1,2,3,4],
    [2,5,6,3],
    [1,2,3,4]
]

df = pd.DataFrame(data)

# Using shape[0] to display the number of rows
print("Before removing:", df.shape[0])

# Using drop_duplicates() to remove duplicate rows
data_cleaned = df.drop_duplicates()

print("After removing duplicates:", data_cleaned.shape[0])

2. Obsługa wartości brakujących:

Najpierw powiedzmy sobie o typach brakujących danych:
- MCAR (Missing Completely At Random) - Brakujące dane są całkowicie losowe i nie są powiązane z żadnymi innymi dostępnymi cechami w zestawie danych.
Przykład:
Załóżmy, że przeprowadzamy badania psychologiczne, w których uczestnicy mają się podzielić pewnymi informacjami osobistymi. Jeżeli osoba wypełniająca ankiety została przypadkowo rozproszona przez inną osobę i przez to zapomniała uzupełnić niektóre odpowiedzi, to taki brak danych jest całkowicie losowy. Brakujące informacje nie wynikają z żadnej właściwości samej osoby czy innych zmiennych w danych, ale są efektem zewnętrznego zakłócenia.

- MAR (Missing At Random) - Brakujące dane są związane z innymi zmiennymi dostępnymi w zestawie danych, jednak nie zależą bezpośrednio od wartości brakującej zmiennej.
Przykład:
Załóżmy, że kwestionariusz pyta respondentów o ilość snu. Część z nich uznała to pytanie za zbyt intymne lub prywatne, dotyczące ich zdrowia i snu, i postanowiła je pominąć. Jednak zauważono, że respondenci, którzy pozytywnie wyrazili się o swoim ogólnym zadowoleniu z życia, częściej podawali wartości odpowiadające optymalnej długości snu, sugerującej zdrowy sen. Z kolei w przypadkach, gdy odpowiedzi na pytanie o zadowolenie z życia były negatywne, częściej odnotowywano brak odpowiedzi na pytanie o długość snu.

- MNAR (Missing Not At Random) - Brak danych jest bezpośrednio powiązany z wartością, której brakuje, co oznacza, że przyczyny braków w danych są systematycznie związane z samą zmienną brakującą.
Przykład:
Kontynuując przykład z badań psychologicznych, załóżmy, że niektóre pytania w ankiecie dotyczą bardzo osobistych aspektów, gdzie przeszkodą do odpowiedzi na takie pytania może być skłonność do introwertyzmu lub inne bliżej nieznane obawy przed dzieleniem się pewnymi informacjami. Osoby o wyższym poziomie introwertyzmu mogą czuć się niekomfortowo, odpowiadając na takie pytania, co prowadzi do selektywnego pomijania ich przez te osoby. Brak odpowiedzi jest w tym przypadku bezpośrednio związany z naturą pytania, co jest charakterystyczne dla sytuacji MNAR, gdzie brak danych wynika z treści pytania lub cech respondentów.

W jaki sposób możemy wypełnić brakujące dane (None)? Możemy użyć do tego średniej, mediany lub mody. Poniżej kodu z ChatGPT:

import pandas as pd
import numpy as np

# Create a sample DataFrame with some missing values
data = {
    'Age': [25, 27, 29, None, 28, 30, None, 29],
    'Salary': [50000, 54000, None, 52000, 55000, None, 53000, 51000],
    'Department': ['HR', 'HR', 'IT', 'IT', 'HR', 'IT', None, 'HR']
}

df = pd.DataFrame(data)

# Display the original DataFrame
print("Original DataFrame:")
print(df)

# Filling missing values in 'Age' using the mean value of the column
# It's suitable for numerical data without extreme values
df['Age'].fillna(df['Age'].mean(), inplace=True)

# Filling missing values in 'Salary' using the median value of the column
# Median is less sensitive to outliers and often more representative for skewed data
df['Salary'].fillna(df['Salary'].median(), inplace=True)

# Filling missing values in 'Department' using the mode (the most frequent value)
# Mode is used for categorical data to fill gaps with the most common category
mode_value = df['Department'].mode()[0]  # Extract the mode value
df['Department'].fillna(mode_value, inplace=True)

# Display the DataFrame after filling missing values
print("\nDataFrame after filling missing values with Mean, Median, and Mode:")
print(df)

mode()[0] zwraca obiekt typu Series, a [0] pozwala na pobranie wartości modalnej o największej częstotliwości występowania z tej serii danych.

inplace to parametr, który może przyjąć wartość True, gdy chcemy dokonać zmian bezpośrednio na oryginalnym obiekcie DataFrame. Gdy parametr przyjmuje wartość False, co jest wartością domyślną, zmiany nie są aplikowane na oryginalnym DataFrame, lecz zwracane jako nowy obiekt, który można przypisać do nowej zmiennej.

Powyższa metoda to tylko jedna z możliwości radzenia sobie z brakującymi danymi.

EDA: Czyszczenie danych - lista operacji (wstęp)

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

Na samym początku, dzięki ChatGPT, wydrukuję listę możliwych operacji do wykonania, których celem jest czyszczenie danych:

  1. Usuwanie duplikatów
  2. Obsługa wartości brakujących
  3. Normalizacja danych
  4. Standaryzacja danych
  5. Oczyszczanie tekstów (usuwanie znaków specjalnych, standaryzacja pisowni)
  6. Przetwarzanie dat i czasu
  7. Kodowanie zmiennych kategorycznych
  8. Wykrywanie i obsługa wartości odstających
  9. Skalowanie cech
  10. Transformacja danych (np. logarytmiczna, potęgowa)
  11. Usuwanie nieistotnych cech
  12. Korekta błędów w danych (np. literówki, błędne etykiety)
  13. Anonimizacja danych osobowych
  14. Walidacja typów danych
  15. Wypełnianie brakujących danych
  16. Segmentacja tekstu (tokenizacja)
  17. Grupowanie podobnych danych
  18. Rozpoznawanie i zamiana synonimów
  19. Usuwanie znaków interpunkcyjnych z tekstu
  20. Zmiana formatu danych (np. z CSV na JSON)
  21. Optymalizacja formatów przechowywania
  22. Filtrowanie danych według kryteriów
  23. Przetwarzanie obrazów (np. usuwanie szumu, zmiana rozdzielczości)
  24. Przetwarzanie dźwięku (np. redukcja szumów, normalizacja głośności)
  25. Obsługa wielojęzycznych danych
  26. Automatyczne etykietowanie danych
  27. Weryfikacja spójności danych
  28. Redukcja wymiarowości (np. PCA, t-SNE)
  29. Implementacja przepływów danych (pipelines)
  30. Monitorowanie jakości danych
  31. Zabezpieczanie przed wpływem danych szkodliwych
  32. Stosowanie ekspresji regularnych do czyszczenia tekstu
  33. Integracja różnych źródeł danych
  34. Wyszukiwanie wzorców i korelacji w danych
  35. Harmonizacja jednostek miar
  36. Przeszukiwanie danych w poszukiwaniu błędów systematycznych
  37. Ujednolicanie formatów adresów
  38. Usuwanie danych wrażliwych
  39. Zastosowanie sztucznej inteligencji do automatycznego czyszczenia danych
  40. Porównywanie i synchronizacja zbiorów danych
  41. Usuwanie danych przeterminowanych
  42. Optymalizacja zapytań dla dużych zbiorów danych
  43. Implementacja asercji danych dla automatycznej weryfikacji
  44. Zastosowanie algorytmów do uczenia maszynowego w celu identyfikacji anomalii
  45. Balansowanie zbiorów danych (np. w kontekście klasyfikacji)
  46. Przygotowanie danych do wizualizacji
  47. Konwersja skal kolorów w obrazach
  48. Zastosowanie filtrów do danych czasowo-ciągłych
  49. Eksploracja danych (data mining) dla identyfikacji ukrytych problemów
  50. Usuwanie informacji nadmiarowych (redundantnych)

Do zagadnień z punktów nr. 3, 4, 9, 45 nawiązałem już w poprzednim wpisie: https://kamilkondrat.blogspot.com/2024/05/exploratory-data-analysis-balansowanie.html

Jeśli chodzi o pozostałe punkty, to niektóre z nich zostaną rozwinięte w kolejnych wpisach, zarówno w formie krótkich opisów, jak i obszerniejszych przykładów.

wtorek, 7 maja 2024

Exploratory Data Analysis: balansowanie zbioru i normalizacja danych

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

Dzisiaj zajmiemy się wybranymi elementami statystyki opisowej, które są kluczowe w kontekście uczenia maszynowego i analizy eksploracyjnej danych (EDA). Omówimy, jak średnia arytmetyczna i odchylenie standardowe pomagają w analizie i przygotowaniu danych.

Średnia arytmetyczna opisuje centralną tendencję zbioru danych, co umożliwia ocenę, czy dane są odpowiednio zrównoważone między klasami. Przywołując ponownie przykład z mojego bloga, gdzie użytkowników podzielono na "zainteresowanych" i "niezainteresowanych" treściami. Załóżmy, że mamy 900 próbek od użytkowników zainteresowanych i 100 próbek od użytkowników niezainteresowanych. Chociaż wiemy, że 900 użytkowników jest zainteresowanych, a 100 nie, naszym celem jest dogłębne zrozumienie cech charakteryzujących obie grupy.

Problem pojawia się, gdy zbiory danych są niezbalansowane. Dominacja danych z grupy zainteresowanych może nieumyślnie wpływać na analizę cech grupy niezainteresowanych, prowadząc do potencjalnych błędów w interpretacji wyników. Może to skutkować sytuacją, w której model oparty na tych danych błędnie klasyfikuje nowe przypadki niezainteresowanych jako zainteresowanych. Innymi słowy, dane dominującej grupy zainteresowanych mogą nieświadomie zaciemniać obraz danych grupy mniejszościowej.

Innymi słowy, pewne cechy zachowań użytkowników niezainteresowanych mogą być mylnie przypisywane do zachowań użytkowników zainteresowanych, co skutkuje błędnym przyporządkowaniem osób niezainteresowanych do grupy zainteresowanych, szczególnie w sytuacji, gdy brakuje odpowiedniej liczby danych dla grupy mniejszościowej (niezainteresowanych). Ta nierównowaga jest od razu widoczna, gdy porównamy liczbę 900 zainteresowanych do 100 niezainteresowanych. Aby to matematycznie uzasadnić, obliczmy współczynnik średniej.

Przyjmijmy, że klasa użytkowników zainteresowanych jest oznaczona wartością 1, a klasa użytkowników niezainteresowanych wartością 0. Mamy 900 użytkowników zainteresowanych i 100 niezainteresowanych, co daje razem 1000 użytkowników.

średnia = (1 * 900 + 0 * 100) / 1000 = 0,9

Współczynnik średniej równy 0,9 wskazuje na niezbalansowane zbiory. Oczekujemy, że wartość średniej dla idealnie zbalansowanego zbioru będzie bliższa 0,5. Należy jednak pamiętać, że to stwierdzenie jest prawdziwe tylko wtedy, gdy klasy są wartościowane jako 0 i 1. W takim przypadku idealnie zbalansowany zbiór miałby wartość średniej równą 0,5. Trzeba mieć na uwadze, że z pewnością istnieją inne przypadki, w których pożądana równowaga między klasami nie będzie przybierać postaci "pół na pół" jak w tym przypadku.

Kod przeprowadzający powyższą operację wyliczenia średniej oraz informację o tym czy zbiór jest zbalansowany czy też nie może wyglądać jak poniżej. Liczba 900 została przekształcona do tablicy dziewięciuset wartości równych 1, a 100 do tablicy wartości równych 0. Następnie te tablice połączono w jedną i użyto na niej gotowej metody mean() z biblioteki numpy, która oblicza średnią:

import numpy as np

# Input data
interested = np.ones(900)  # Creates an array of 900 values, all set to 1
not_interested = np.zeros(100)  # Creates an array of 100 values, all set to 0

# Combine the data into one array
data = np.concatenate([interested, not_interested])

# Calculate the mean
mean = np.mean(data)

print(f"The mean is: {mean}")

# Check if the dataset is balanced
print("The dataset is " + ("balanced" if mean == 0.5 else "unbalanced"))

Kolejnym zastosowaniem średniej wraz z odchyleniem standardowym jest normalizacja danych, co jest kluczowe w przetwarzaniu danych liczbowych przez algorytmy uczenia maszynowego. Odchylenie standardowe to miara rozproszenia wartości wokół średniej w zestawie danych. Przykładowo, w modelu regresji cen mieszkań możemy rozważać takie cechy, jak rok budowy obiektu, na przykład 1999, 2011 czy 2017, oraz ilość pokoi, takich jak 1, 2 lub 3.

Surowe dane jak rok 1999 czy liczba pokoi 1, mogą być mylące dla modelu, jeśli nie zostaną odpowiednio znormalizowane. Nie zagłębiając się w szczegóły matematyczne, istotne jest, aby zrozumieć, że tak różne wartości z obcych sobie klas, przetwarzane równocześnie, mogą generować chaos. Różnica między wartościami jak rok budowy i ilość pokoi jest znacząca i może znacznie wpływać na wyniki modelowania.

Gdybyśmy napotkali dane, w których rok budowy wynosiłby 1999, a inny rekord zawierałby rok równy 1, byłoby to zjawisko nietypowe. Teoretycznie moglibyśmy przypuszczać, że mamy do czynienia z budynkiem zabytkowym. W takiej sytuacji moglibyśmy zdecydować, czy utrzymać te dane w zbiorze treningowym modelu, czy też odrzucić takiego outliera, czyli wartość znacząco odbiegającą od średniej.

Jednakże, gdy dane, w których rok budowy 1999r. jest zestawiony z liczbą pokoi równą 1, znajdują się razem w jednym wektorze danych uczących, może to znacznie obniżyć wartość modelu w kontekście dokładnych predykcji. W związku z tym, poniżej przedstawię metodę normalizacji danych, która pozwoli uniknąć tego typu problemów:

import pandas as pd
from sklearn.preprocessing import StandardScaler

# Sample data
data = {
    'year_built': [1999, 2011, 2017],
    'number_of_rooms': [1, 2, 3]
}

# Creating a DataFrame
df = pd.DataFrame(data)

# Display the original data
print("Original Data:")
print(df)

# Initialize the StandardScaler
scaler = StandardScaler()

# Fit and transform the data
normalized_data = scaler.fit_transform(df)

# Creating a DataFrame for the normalized data
normalized_df = pd.DataFrame(normalized_data, columns=['year_built', 
                                                       'number_of_rooms'])

# Display the normalized data
print("\nNormalized Data:")
print(normalized_df)

Nie będę tworzył pełnego opisu kodu, natomiast pozwolę sobie wyróżnić kilka rzeczy.

StandardScaler to klasa służąca do normalizacji danych.

data to słownik z listami zawierającymi wartości liczbowe.

fit_transform() oblicza średnią i odchylenie standardowe, aby w kolejnym kroku skalować każdą wartość w kolumnie tak, aby średnia wynosiła 0, a odchylenie standardowe 1.

Nie wszystko jest tak idealne, jak mogłoby się wydawać. Muszę zauważyć, że normalizacja danych ilościowych, takich jak liczba pokoi, niekoniecznie pasuje do danych porządkowych, takich jak lata. Poniżej przedstawiam kod, który normalizuje liczbę pokoi w zakresie od 0 do 1, pozostawiając dane o latach bez zmian. Zamiast używać StandardScaler, zastosowałem MinMaxScaler. Kod został opracowany z pomocą ChatGPT:

import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# Sample data
data = {
    'year_built': [1999, 2011, 2017],
    'number_of_rooms': [1, 2, 3]
}

# Creating a DataFrame
df = pd.DataFrame(data)

# Display the original data
print("Original Data:")
print(df)

# Initialize the MinMaxScaler
scaler = MinMaxScaler()

# Fit and transform the data
normalized_data = scaler.fit_transform(df[['number_of_rooms']])

# Creating a DataFrame for the normalized data
# We only apply scaling to 'number_of_rooms' to avoid distorting 
# the ordinal nature of 'year_built'
normalized_df = pd.DataFrame(data={'year_built': df['year_built'], 
                                   'number_of_rooms': normalized_data.flatten()})

# Display the normalized data
print("\nNormalized Data:")
print(normalized_df)

Cóż, czy to wyczerpuje temat? Myślę, że nie. Ja również ciągle się uczę... Ważne jest, aby nieustannie się rozwijać, podchodzić krytycznie do swojej pracy i nieustannie poszukiwać nowych, lepszych rozwiązań.

poniedziałek, 6 maja 2024

Exploratory Data Analysis (EDA) - wstęp

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

Chciałbym rozpocząć serię wpisów na temat eksploracyjnej analizy danych, znaną również jako badawcza analiza danych. Oba te terminy są powszechnie używane. Często spotyka się również określenie wstępna analiza danych jako synonim Exploratory Data Analysis (EDA). Dla uproszczenia, w dalszych wpisach będę używał skrótu EDA, odnosząc się do tego procesu.

We wstępie pozwolę sobie przedstawić ogólną definicję EDA oraz wylistować kluczowe zagadnienia związane z tym tematem, aby w kolejnych wpisach poświęcić uwagę każdemu z wymienionych punktów.

Najpierw zwięzła definicja ( https://www.ibm.com/topics/exploratory-data-analysis ):

Exploratory data analysis (EDA) is used by data scientists to analyze and investigate data sets and summarize their main characteristics, often employing data visualization methods.

EDA helps determine how best to manipulate data sources to get the answers you need, making it easier for data scientists to discover patterns, spot anomalies, test a hypothesis, or check assumptions.

EDA is primarily used to see what data can reveal beyond the formal modeling or hypothesis testing task and provides a provides a better understanding of data set variables and the relationships between them. It can also help determine if the statistical techniques you are considering for data analysis are appropriate. Originally developed by American mathematician John Tukey in the 1970s, EDA techniques continue to be a widely used method in the data discovery process today.

A poniżej, przy pomocy ChatGPT, lista najważniejszych punktów związanych z EDA:
  1. Statystyka opisowa

    • Średnia
    • Mediana
    • Moda
    • Zakres
    • Wariancja
    • Odchylenie standardowe
    • Kwartyly
  2. Wizualizacja danych

    • Histogram
    • Wykres pudełkowy (Box plot)
    • Wykres punktowy (Scatter plot)
    • Wykres słupkowy (Bar chart)
    • Wykres liniowy (Line chart)
    • Heatmapy
    • Pair plots
    • Violin plots
  3. Czyszczenie danych

    • Brakujące wartości
    • Outliery
    • Normalizacja
    • Standaryzacja
    • Przekształcenie danych
  4. Korelacja i zależności

    • Współczynnik korelacji Pearsona
    • Współczynnik korelacji Spearmana
    • Matryca korelacji
    • Testy statystyczne
  5. Analiza skupień

    • Wielowymiarowa analiza
    • Redukcja wymiarowości
    • PCA (Principal Component Analysis)
    • t-SNE (t-Distributed Stochastic Neighbor Embedding)
  6. Hipotezy i wnioskowanie

    • Testy statystyczne
    • p-wartość
    • Testy normalności
    • Testy nieparametryczne
  7. Narzędzia i języki programowania

    • Python
    • R
    • Pandas
    • Matplotlib
    • Seaborn
    • SciPy
    • NumPy
  8. Raportowanie wyników

    • Storytelling z danymi
    • Dashboardy
    • Interaktywne wizualizacje

niedziela, 5 maja 2024

Podejście zorientowane na dane (Data Centric Approach)

Ten wpis, podobnie jak cała zawartość bloga, odzwierciedla moje zainteresowania rozwojem w dziedzinie informatyki. Główne cele tego przedsięwzięcia to dzielenie się wiedzą, demonstracja moich umiejętności oraz chęć poznawania nowych zagadnień, co może zainteresować potencjalnych współpracowników zarówno w sferze zawodowej, jak i poza nią. Blog ten jest również okazją do samodzielnego przetwarzania zdobytej wiedzy i tworzenia osobistych notatek. Jako że sam jestem w trakcie nauki, zachęcam do niezależnego myślenia i, jeśli tematyka wpisów wpisuje się w zakres Twoich zainteresowań, do dalszej eksploracji i weryfikacji podanych przeze mnie informacji.

W tej notce posłużę się pracą naukową ( https://arxiv.org/abs/2303.10158 ), wyciągając z niej interesujący mnie fragment, istotny z punktu widzenia tematu wpisu:

In the past, AI was often viewed as a model-centric field, where the focus was on advancing model designs given fixed datasets. However, the overwhelming reliance on fixed datasets does not necessarily lead to better model behavior in real-world applications, as it overlooks the breadth, difficulty, and fidelity of data to the underlying problem [ 155 ]. Moreover, the models are often difficult to transfer from one problem to another since they are highly specialized and tailored to specific problems. Furthermore, undervaluing data quality could trigger data cascades [ 200], causing negative effects such as decreased accuracy and persistent biases [ 36]. This can severely hinder the applicability of AI systems, particularly in high-stakes domains.
Źródło: https://arxiv.org/pdf/2303.10158 (str. 4)

Powyższy fragment konfrontuje podejście zorientowane na dane z podejściem skoncentrowanym na modelach, wskazując między innymi na sztywność modeli i ich ograniczone zdolności adaptacyjne do przetwarzania różnych danych, a także na zbyt małe skupienie na jakości danych. Jednym z terminów, który może być nieznany, jest data cascades, co oznacza lawinowe konsekwencje wynikające z użycia niewłaściwego zbioru danych. Model wytrenowany na takich danych początkowo może wydawać się efektywny, jednak z czasem mogą ujawnić się różne niepożądane sytuacje, w których model działa szkodliwie w ważnych aspektach, takich jak na przykład ratowanie życia. 

Dodatkowym problemem jest trudność w naprawieniu takiej sytuacji, ponieważ końcowe problemy wynikają z błędów na wczesnym etapie, a dane, na których model był szkolony, były nieodpowiednie. W związku z takimi sytuacjami zaczęto przywiązywać większą wagę do danych i ich kluczowej roli w procesie. To między innymi przyczyniło się do powstania trendu, w którym znacznie większą uwagę przykłada się do jakości i precyzji danych, znanego jako data-centric approach.

Z kolei o accuracy pisałem przy okazji KPI: https://kamilkondrat.blogspot.com/2024/05/kpi-w-projektach-data-sciencemachine.html . Jeśli chodzi o persistent biases, można to opisać jako pewnego rodzaju znaczące „skrzywienie poznawcze”, jak to sam osobiście nazwę. Na przykład, model może wykazywać skłonność do klasyfikowania obrazów autobusów jako ciężarówek, ponieważ był wytrenowany głównie na różnorodnych obrazach ciężarówek, a dane dotyczące autobusów były niewystarczające. To „skrzywienie” modelu do ocen jest trwałe, co oznacza, że model może kontynuować błędne klasyfikacje, nawet po próbach korekty.

Poniżej dalsza część artykułu. Tym razem, kolejny fragment będzie zawierał między innymi wzmiankę o tym gdzie to GPT-2 w porównaniu do GPT-3 odnotował niewielkie modyfikacje w architekturze sieci neuronowych, a za to skupiono się na zebraniu znacznie większej ilości danych, wysokiej jakości danych, do trenowania modelu:

Consequently, the attention of researchers and practitioners has gradually shifted toward data-centric AI to pursue data excellence [9]. Data-centric AI places a greater emphasis on enhancing the quality and quantity of the data with the model relatively more fixed. While this transition is still ongoing, we have already witnessed several accomplishments that shed light on its benefits. For example, the advancement of large language models is greatly dependent on the use of huge datasets [ 34, 121 , 187 , 188 ]. Compared to GPT-2 [188 ], GPT-3 [ 34] only made minor modifications in the neural architecture while spending efforts collecting a significantly larger high-quality dataset for training. ChatGPT [174 ], a remarkably successful application of GPT-3, adopts a similar neural architecture as GPT-3 and uses a reinforcement learning from human feedback procedure [48] to generate high-quality labeled data for fine-tuning. A new approach, known as prompt engineer-ing [ 146], has seen significant success by focusing solely on tuning data inputs. The benefits of data-centric approaches can also be validated by practitioners [169, 189 , 241 ]. For instance, Landing AI, a computer vision company, observes improved accuracy, reduced development time, and more consistent and scalable methods from the adoption of data-centric approaches [ 169 ]. All these achievements demonstrate the promise of data-centric AI.
Źródło: https://arxiv.org/pdf/2303.10158 (str. 4, 5)

...To niewątpliwie dodaje rację bytu data-centric approach. A teraz, na koniec tego wpisu, fragment który zawiera m.in. upomnienie przez Autorów pracy, że podejście nastawione na dane jak i podejście nastawione na model może istnieć równolegle i wzajemnie się uzupełniać :-) :

It is noteworthy that data-centric AI does not diminish the value of model-centric AI. Instead, these two paradigms are complementarily interwoven in building AI systems. On the one hand, model-centric methods can be used to achieve data-centric AI goals. For example, we can utilize a generation model, such as GAN [ 86 , 283 ] and diffusion model [ 101, 124 , 194 ], to perform data augmentation and generate more high-quality data. On the other hand, data-centric AI could facilitate the improvement of model-centric AI objectives. For instance, the increased availability of augmented data could inspire further advancements in model design. Therefore, in production scenarios, data and models tend to evolve alternatively in a constantly changing environment [183].
Źródło: https://arxiv.org/pdf/2303.10158 (str. 5)

Analiza sentymentów - wpisy na mediach społecznościowych (podział danych)

Ten wpis zaczniemy od stworzenia DataFrame z danymi treningowymi train_df = pd.read_csv('train.csv', encoding='ISO-8859-1')....