Python divide por cero en log – regresión logística

Estoy tratando de implementar un clasificador de regresión logística multiclase que distingue entre k clases diferentes.

Este es mi código.

 import numpy as np from scipy.special import expit def cost(X,y,theta,regTerm): (m,n) = X.shape J = (np.dot(-(yT),np.log(expit(np.dot(X,theta))))-np.dot((np.ones((m,1))-y).T,np.log(np.ones((m,1)) - (expit(np.dot(X,theta))).reshape((m,1))))) / m + (regTerm / (2 * m)) * np.linalg.norm(theta[1:]) return J def gradient(X,y,theta,regTerm): (m,n) = X.shape grad = np.dot(((expit(np.dot(X,theta))).reshape(m,1) - y).T,X)/m + (np.concatenate(([0],theta[1:].T),axis=0)).reshape(1,n) return np.asarray(grad) def train(X,y,regTerm,learnRate,epsilon,k): (m,n) = X.shape theta = np.zeros((k,n)) for i in range(0,k): previousCost = 0; currentCost = cost(X,y,theta[i,:],regTerm) while(np.abs(currentCost-previousCost) > epsilon): print(theta[i,:]) theta[i,:] = theta[i,:] - learnRate*gradient(X,y,theta[i,:],regTerm) print(theta[i,:]) previousCost = currentCost currentCost = cost(X,y,theta[i,:],regTerm) return theta trX = np.load('trX.npy') trY = np.load('trY.npy') theta = train(trX,trY,2,0.1,0.1,4) 

Puedo verificar que el costo y el gradiente están devolviendo los valores que están en la dimensión correcta (el costo devuelve un escalar y el gradiente devuelve un vector de fila 1 por n), pero aparece el error

 RuntimeWarning: divide by zero encountered in log J = (np.dot(-(yT),np.log(expit(np.dot(X,theta))))-np.dot((np.ones((m,1))-y).T,np.log(np.ones((m,1)) - (expit(np.dot(X,theta))).reshape((m,1))))) / m + (regTerm / (2 * m)) * np.linalg.norm(theta[1:]) 

¿Por qué sucede esto y cómo puedo evitar esto?

Puede limpiar la fórmula utilizando apropiadamente la transmisión, el operador * para productos de puntos de vectores, y el operador @ para la multiplicación de matrices, y dividiéndolo como se sugiere en los comentarios.

Aquí está su función de costo:

 def cost(X, y, theta, regTerm): m = X.shape[0] # or y.shape, or even p.shape after the next line, number of training set p = expit(X @ theta) log_loss = -np.average(y*np.log(p) + (1-y)*np.log(1-p)) J = log_loss + regTerm * np.linalg.norm(theta[1:]) / (2*m) return J 

Puedes limpiar tu función de degradado siguiendo las mismas líneas.

Por cierto, ¿estás seguro de que quieres np.linalg.norm(theta[1:]) ? Si está intentando realizar la regularización de L2, el término debería ser np.linalg.norm(theta[1:]) ** 2 .

La solución adecuada aquí es agregar un poco de épsilon al argumento de la función de log . Lo que funcionó para mí fue

 epsilon = 1e-5 def cost(X, y, theta): m = X.shape[0] yp = expit(X @ theta) cost = - np.average(y * np.log(yp + epsilon) + (1 - y) * np.log(1 - yp + epsilon)) return cost 

Supongo que sus datos tienen valores negativos en ella. No se puede registrar un negativo.

 import numpy as np np.log(2) > 0.69314718055994529 np.log(-2) > nan 

Hay muchas maneras diferentes de transformar sus datos que deberían ayudar, si este es el caso.