How to train a Binary Logistic Classifier with One Input Variable?

Viewed 35

Binary Logistic Classifier with One Input Variable

Consider the following starting code using the Iris dataset:

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets

iris = datasets.load_iris()

x = iris.data[:, 3:4]   # petal width

Using only petal width as the input variable, implement a binary logistic regression classifier with scikit-learn to determine whether a flower belongs to the Setosa class or not.

The model should have the form

proba.png

where (x) is the petal width.

Question

What values do you obtain for (\theta_0) and (\theta_1), and what petal-width value corresponds approximately to a classification probability of (0.5)?

Include the relevant code and the numerical results obtained from your implementation.

Your explanation must refer specifically to the values produced by your program. Generic definitions or explanations that are not connected to your numerical results will not receive full credit.

Verification: You may be asked to explain one instruction, reproduce one numerical result, or modify the classifier during the laboratory session. If the submitted solution cannot be explained or reproduced, the corresponding points may be canceled.

2 Answers

Para realizar el ejercicio con la libreria requerida, primero pegué el codigo base, el cual, requiere la instalacion de la libreria previo a poder ejecutar, se extrae el dataset en una variable y se le asignan los valores del ancho de petalo a la variable x

codigo_answe.jpeg

La libreria incluye un metodo ya de regresor logistico, hay que importarlo para poder trabajar con los datos, se le asigna el valor esperado a y, que será cero para definir la clase setosa,luego se entrena el modelo con un valor de regularización alto para obtener los valores mas acertados, luego se extraen los valores de theta0, theta1 y finalmente con ellos, se calcula el ancho de petalo para una probabilidad de 50%

rlg_answer.jpeg

Resultados:

resultados_answer.jpeg

Lo primero es importar los datos de nuestro dataset, en este caso se encuentran en la librería scikit-learn. Con la librería instalada, extraemos los datos:

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets

iris = datasets.load_iris()

x = iris.data[:, 3:4]   # petal width
y = iris.target
print(y)

Los valores de "y" son 0, 1 o 2 según el tipo de flor, esto se muestra en la siguiente imagen:
1.png
Al revisar nuestros datos se puede ver que el tipo setosa corresponde al número 0, entonces para nuestro clasificador hacemos que solo sean 1 o 0 los valores de “y”, donde 1 corresponde a setosa y 0 a uno de los otros dos tipos. Esto se hace con la siguiente instrucción y se visualiza el cambio de datos en la imagen:

y = (y==0).astype(float) 
print(y)

2.png

Se importa la clase del modelo de regresión, creamos un modelo con una variable que será de esa clase. Después, se entrena el modelo, para esto se utiliza la función fit() y se le mandan las entradas (x) y los datos de target “y”. Ahora no se necesitó crear una matriz con la primera columna de 1’s, la función ya lo hace, solo hay que mandar los valores de x1.

from sklearn.linear_model import LogisticRegression
modelo = LogisticRegression()
modelo.fit(X=x,y=y)

Con lo anterior ya está el modelo listo, ahora solo se extraen los valores de θ y se imprimen para conocer su valor. Se utiliza la función item() para los valores debido a que estos se encuentran en un arreglo aunque solo son un dato, θ_0 esta en un [] y θ_1 en [[]]. Se puede ver que los nombres donde se encuentran los valores de theta hacen referencia a la ecuación de la recta, donde θ_0 corresponde al cruve con el eje vertical (intercepción) y θ_1 a la pendiente o coeficiente de la entrada.

theta0 = modelo.intercept_.item()
theta1 = modelo.coef_.item()
print(f"theta0 = {theta0}")
print(f"theta1 = {theta1}")

Al imprimirlos tenemos que:
3.png
Ahora que ya conocemos nuestro modelo podemos observar que es lo que nos entrega si lo evaluamos en un rango de x (en este caso de -1 a 3), es necesario utilizar .reshape(-1,1) para que tengamos un vector de n filas y 1 columna. Al evaluar con predict_proba() e imprimir podremos visualizar los datos obtenidos.

x_prueba = np.linspace(-1,3,20).reshape(-1,1)
print(x_prueba)
ymodelo=modelo.predict_proba(x_prueba)
print(ymodelo)

En la siguiente figura observamos nuestro vector de x que se meterá al modelo, el rango de -1 a 3 se elegió para que se alcance a visualizar la forma de sigmoide:
4.png
En la siguiente figura tenemos los valores obtenidos del modelo, donde la primera columna es la probabilidad de que sea 0 y la segunda columna la probabilidad de obtener un 1.
5.png
Con estos datos se puede graficar el modelo y ver que tiene un comportamiento como la función sigmoide. Para esto se grafican los datos de “x” y “y” del modelo original (los “y” ya convertidos en 0 y 1), también se grafica nuestro modelo evaluado, pero únicamente se toma la segunda columna que indica la probabilidad de que sea 1.

plt.plot(x,y, '.k')
plt.plot(x_prueba, ymodelo[:, 1], '.r')
plt.xlabel("Ancho del pétalo")
plt.ylabel("Probabilidad")
plt.xlim(-0.8,3)
plt.show()

6.png
Finalmente, para conocer qué valor corresponde a la probabilidad de 0.5 hay que recordar nuestro modelo:
y^ = θ_0 + θ_1 x1
También si recordamos la función sigmoide = 1/(1+e^-modelo)
Entonces tendremos 0.5 cuando nuestro modelo será igual a cero. Simplemente igualamos a cero y despejamos x1:
x1=-θ_0/θ_1

x1=-theta0/theta1
print(f"El valor de ancho para 0.5 es: {x1}")

Esto nos da el siguiente resultado:
7.png