This commit is contained in:
szymonj98 2022-05-18 00:17:17 +02:00
parent 5797dede2d
commit 2392c36421
2 changed files with 7446 additions and 9 deletions

7257
mushrooms.tsv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -106,6 +106,8 @@
"\n", "\n",
"$P(X|K) = P(x1|K)*P(x2|K)*...*P(xn|K)$\n", "$P(X|K) = P(x1|K)*P(x2|K)*...*P(xn|K)$\n",
"\n", "\n",
"Zauażmy że w rzeczywistości $P(X|K)$ obliczymy z twierdzenia bayesa, jednak dzięki temu że nasz klasyfikator jest naiwny zakładamy niezależność cech $x1, x2,...,xn$ więc możemy uprościć obliczenia do powyższego wzoru\n",
"<br><br><br>\n",
"$P(xk|K) = \\frac{Liczba\\ elementów\\ klasy\\ K\\ dla\\ których\\ wartość\\ cechy\\ Ak\\ jest\\ równa\\ xk}{liczba\\ wszystkich\\ obiektów\\ klasy\\ K}$\n", "$P(xk|K) = \\frac{Liczba\\ elementów\\ klasy\\ K\\ dla\\ których\\ wartość\\ cechy\\ Ak\\ jest\\ równa\\ xk}{liczba\\ wszystkich\\ obiektów\\ klasy\\ K}$\n",
"<br><br><br><br>\n", "<br><br><br><br>\n",
"<b>Powyższy wzór ma jedna pewne problemy z zerowymi prawdopodobieństwami</b>\n", "<b>Powyższy wzór ma jedna pewne problemy z zerowymi prawdopodobieństwami</b>\n",
@ -117,15 +119,15 @@
"<br><br><br>\n", "<br><br><br>\n",
"<b>Wygładzanie Laplace'a</b>\n", "<b>Wygładzanie Laplace'a</b>\n",
"<br><br><br>\n", "<br><br><br>\n",
"Wygładzanie Laplace'a zwane jest również wygładzaniem + 1, jest to bardzo prosty sposób wystarczy dla każdego $P(xK|K)$ dodać do licznika 1 a do mianownika dodać liczbę cech obiektu $X = (x1,x2,...,xn)$:\n", "Wygładzanie Laplace'a zwane jest również wygładzaniem + 1, jest to bardzo prosty sposób wystarczy dla każdego $P(xk|K)$ dodać do licznika 1 a do mianownika dodać liczbę klas obiektu, dodając 1 do licznika możemy to interpretować jako dodanie nowego obiektu do klasy, robiąc to dla każdej klasy \"mamy\" dodatkowe obiekty równe liczbie klas dlatego do mianownika musimy dodać liczbę klas.\n",
"\n", "\n",
"$P(xk|K) = \\frac{(Liczba\\ elementów\\ klasy\\ K\\ dla\\ których\\ wartość\\ cechy\\ Ak\\ jest\\ równa\\ xk\\\\)\\ + 1}{(liczba\\ wszystkich\\ obiektów\\ klasy\\ K\\\\) + n}$\n", "$P(xk|K) = \\frac{(Liczba\\ elementów\\ klasy\\ K\\ dla\\ których\\ wartość\\ cechy\\ Ak\\ jest\\ równa\\ xk\\\\)\\ + 1}{(liczba\\ wszystkich\\ obiektów\\ klasy\\ K\\\\) + liczba klas}$\n",
"\n", "\n",
"Łatwo można zauważyć że samo dodanie 1 do licznika nie jest wystarczające ponieważ wtedy $P(xK|K)$ mogłoby być $> 1$\n", "Łatwo można zauważyć że samo dodanie 1 do licznika nie jest wystarczające ponieważ wtedy $P(xk|K)$ mogłoby być $> 1$\n",
"<br><br><br>\n", "<br><br><br>\n",
"Dzięki wygładzaniu Laplace'a $P(X|K)$ nigdy nie bęzie zerowe minimalna wartość to\n", "Dzięki wygładzaniu Laplace'a $P(X|K)$ nigdy nie bęzie zerowe minimalna wartość to\n",
"\n", "\n",
"$\\frac{n}{(liczba\\ wszystkich\\ obiektów\\ klasy\\ K\\\\) + n}$\n", "$\\frac{1}{n *(liczba\\ wszystkich\\ obiektów\\ klasy\\ K\\\\) + liczba\\ klas}$\n",
"<br><br><br>\n", "<br><br><br>\n",
"\n" "\n"
] ]
@ -135,21 +137,199 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"<b>Implementacja</b>\n", "<b>Implementacja</b>\n",
"\n", "\n"
"<b>Naiwny klasyfikator bayesowski można stosować w klasyfikacji tekstu np filtry antyspamowy lub jak w naszym przykładzie klasyfikacja tekstu na...</b>"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 1,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [] "source": [
"import pandas as pd\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import accuracy_score"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"#przygotowanie prawdopodobienstw wartosci danych cech w zaleznosci od klasy\n",
"def getDictOfAttribProbs(clas,className,attribsNames,data):\n",
" dictionaries = {}\n",
" for value in clas:\n",
" classFreq = {}\n",
" for i in range(len(attribsNames)):\n",
" classData = data[data[className] == value]\n",
" freq = {}\n",
" attribData = classData[attribsNames[i]]\n",
" for attrib in attribData:\n",
" count = freq.get(attrib,1) + 1\n",
" freq[attrib] = count\n",
" freq = {k : v / len(classData) for k,v in freq.items()}\n",
" classFreq[attribsNames[i]] = freq\n",
" dictionaries[value] = classFreq\n",
" return dictionaries"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"#a priori dla klas\n",
"def classProb(clas,data):\n",
" x = len(data[data['edible']==clas]['edible'])\n",
" y = len(data['edible'])\n",
" return x/y"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"#prawdopodobienstwo dla wartosic danej cechy w zaelznosci od klasy\n",
"def getAttribProbs(attrib,value,data,clas,dictProbs):\n",
" return dictProbs[clas][attrib].get(value,1.0/len(data))"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"#a posteriori dla danego obiektu \n",
"def getPosteriori(attribs,attribsNames,clas,dictProbs):\n",
" dic = {}\n",
" for i in range(len(attribs)):\n",
" dic[attribsNames[i]] = attribs[i]\n",
" sum = 1.0\n",
" for key in dic:\n",
" sum = sum * getAttribProbs(key,dic[key],X_train,clas,dictProbs)\n",
" return sum * classProb(clas,X_train)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"#predykcja dla danych\n",
"def predict(data, clas,model):\n",
" attribNames = data.columns\n",
" predictions = []\n",
" for i in range(len(data)):\n",
" probs = {}\n",
" for name in clas:\n",
" probs[name] = getPosteriori(list(data.iloc[i]),list(attribNames),name,model)\n",
" keyMax = max(zip(probs.values(),probs.keys()))[1]\n",
" predictions.append(keyMax)\n",
" return predictions"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"features=[\n",
" 'edible',\n",
" 'cap-shape',\n",
" 'cap-surface',\n",
" 'cap-color',\n",
" 'bruises',\n",
" 'odor',\n",
" 'gill-attachment',\n",
" 'gill-spacing',\n",
" 'gill-size',\n",
" 'gill-color',\n",
" 'stalk-shape',\n",
" 'stalk-root',\n",
" 'stalk-surface-above-ring',\n",
" 'stalk-surface-below-ring',\n",
" 'stalk-color-above-ring',\n",
" 'stalk-color-below-ring',\n",
" 'veil-type','veil-color',\n",
" 'ring-number','ring-type',\n",
" 'spore-print-color',\n",
" 'population',\n",
" 'habitat'\n",
"]\n",
"\n",
"mushrooms = pd.read_csv('mushrooms.tsv', sep='\\t',names=features)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test = train_test_split(mushrooms, test_size=0.2, random_state=0,stratify=mushrooms['edible'])\n",
"columns = ['odor','cap-color','gill-spacing','stalk-surface-above-ring','habitat']\n",
"className = 'edible'\n",
"classValue = list(set(X_train['edible']))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"model = getDictOfAttribProbs(classValue,className,columns,X_train)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9889807162534435\n"
]
}
],
"source": [
"X_test_data = X_test[columns]\n",
"X_test_results = X_test[className]\n",
"pred = predict(X_test_data,classValue,model)\n",
"print(accuracy_score(list(X_test_results),pred))"
]
} }
], ],
"metadata": { "metadata": {
"interpreter": {
"hash": "393784674bcf6e74f2fc9b1b5fb3713f9bd5fc6f8172c594e5cfa8e8c12849bc"
},
"kernelspec": {
"display_name": "Python 3.9.2 64-bit",
"language": "python",
"name": "python3"
},
"language_info": { "language_info": {
"name": "python" "codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.2"
}, },
"orig_nbformat": 4 "orig_nbformat": 4
}, },