Categorías
Python

Instalación de Python en Windows, MacOS y Linux

 

Tabla de Contenidos

  • Diferenciando SciPy el ecosistema y SciPy la Biblioteca
  • Comprender SciPy Módulos
  • Instalación SciPy en su ComputerAnacondaPip
  • Anaconda
  • Pip
  • Uso del módulo Cluster en SciPy
  • Uso del módulo Optimizar en SciPyMinimizing una función con un VariableMinimizing una función con muchas variables
  • minimización de una función con una variable
  • minimización de una función con muchas variables
  • Conclusión
  • Anaconda
  • Pip
  • minimización de una función con una variable
  • minimización de una función con muchas variables

Cuando usted quiere hacer el trabajo científico en Python, la primera biblioteca se puede recurrir es SciPy . Como se verá en este tutorial, SciPy no es sólo una biblioteca, pero en su conjunto ecosistema de bibliotecas que trabajan en conjunto para ayudar a lograr complicado tareas científicas forma rápida y fiable.

En este tutorial, aprenderá a:

  • buscar información sobre todas las cosas que puede hacer con SciPy
  • Instalar SciPy en su ordenador
  • Uso SciPy a agruparse un conjunto de datos de varias variables
  • Uso SciPy para encontrar el óptimo de una función de buceo

Vamos en el maravilloso mundo de SciPy! Bono

gratuito: Haga clic aquí para obtener acceso a una hoja de trucos Conda con ejemplos de uso práctico para la gestión de su medio ambiente y los paquetes de Python.

Diferenciando SciPy el ecosistema y SciPy la Biblioteca

Cuando se desea utilizar Python para tareas de computación científica, hay varias bibliotecas que es probable que se aconseja el uso, incluyendo:

  • NumPy
  • SciPy
  • Matplotlib
  • IPython
  • sympy
  • pandas

Colectivamente, estas bibliotecas constituyen el ecosistema SciPy y están diseñados para trabajar juntos. Muchos de ellos se basan directamente en las matrices NumPy hacer cálculos. En este tutorial se espera que usted tiene cierta familiaridad con la creación de matrices NumPy y operar en ellos.

Nota: Si necesita una cartilla rápida o de actualización sobre NumPy, a continuación, puede consultar los siguientes tutoriales:

  • Look Ma, pero no los fines de Bucles: Programación matriz con NumPy
  • NumPy arange (): cómo usar np.arange ()
  • MATLAB vs Python: una visión general de la matriz de operaciones básicas

En este tutorial, aprenderá acerca de la SciPy biblioteca , uno de los componentes básicos del ecosistema SciPy. El SciPy biblioteca es la biblioteca fundamental para la computación científica en Python. Proporciona muchas interfaces eficientes y fáciles de usar para tareas tales como la integración numérica, optimización, procesamiento de señales, álgebra lineal, y más. La comprensión de biblioteca SciPy Módulos

El SciPy

se compone de un número de módulos de que separan la biblioteca en unidades funcionales distintas. Si usted quiere aprender acerca de los diferentes módulos que SciPy incluye, a continuación, puede ejecutar la ayuda () en scipy, como se muestra a continuación:

>>> import scipy
>>> help(scipy)

Esto produce alguna salida ayuda para toda la biblioteca SciPy, una parte del cual se muestra a continuación : código

Subpackages
-----------

Using any of these subpackages requires an explicit import. For example,
``import scipy.cluster``.

::

cluster --- Vector Quantization / Kmeans
fft --- Discrete Fourier transforms
fftpack --- Legacy discrete Fourier transforms
integrate --- Integration routines
...

Este bloque muestra la porción de subpaquetes de la salida de la ayuda, que es una lista de todos los módulos disponibles dentro SciPy que se puede utilizar para los cálculos.

Tenga en cuenta el texto en la parte superior de la sección que establece: «El uso de cualquiera de estos sub-paquetes requiere una importación explícita.» Cuando se desea utilizar la funcionalidad de un módulo en SciPy, debe importar el módulo que desea utilizar específicamente . Vas a ver algunos ejemplos de esto un poco más adelante en el tutorial, y las directrices para la importación de bibliotecas de SciPy se muestran en la documentación SciPy.

Una vez que decida qué módulo que desea utilizar, puede revisar la referencia de la API SciPy, que contiene todos los detalles acerca de cada módulo en SciPy. Si usted está buscando algo con un poco más de la exposición, a continuación, las notas de la conferencia SciPy son un gran recurso para ir a fondo de muchos de los módulos SciPy.

Más adelante en este tutorial, usted aprenderá acerca de cluster y Optimizar, que son dos de los módulos de la biblioteca SciPy. Pero en primer lugar, tendrá que instalar SciPy en su ordenador.

Instalación SciPy en el equipo

Al igual que con la mayoría de los paquetes de Python, hay dos formas principales para instalar en su ordenador SciPy:

Aquí, usted aprenderá cómo utilizar estos dos enfoques para instalar la biblioteca. única dependencia directa de SciPy es el paquete NumPy. Cualquiera de los métodos de instalación instalará automáticamente NumPy además de SciPy, si es necesario.

Anaconda

Anaconda es una popular distribución de Python, principalmente debido a que incluye versiones de los paquetes de la mayoría de divulgación científica Python pre-construidos para Windows, MacOS y Linux. Si usted no tiene Python instalado en el equipo en absoluto, sin embargo, a continuación, Anaconda es una gran opción para empezar a utilizar. Anaconda viene pre-instalado con SciPy y sus dependencias requeridas, así que una vez que haya instalado anaconda, que no es necesario hacer nada más!

Puede descargar e instalar Anaconda desde su página de descargas. Asegúrese de descargar la versión más reciente de Python 3. Una vez que tenga el instalador en su ordenador, se puede seguir el procedimiento de configuración por defecto para una aplicación, dependiendo de la plataforma.

Nota: Asegúrese de instalar Anaconda en un directorio que no requiere permisos de administrador modificar. Esta es la configuración predeterminada en el instalador.

Si ya tiene instalado Anaconda, pero desea instalar o actualizar SciPy, entonces usted puede hacer eso, también. Abrir una aplicación de terminal en MacOS o Linux, o la Anaconda Prompt en Windows y escriba una de las siguientes líneas de código:

$ conda install scipy
$ conda update scipy

Se debe utilizar la primera línea si necesita instalar SciPy o la segunda línea si lo que desea actualizar SciPy. Para asegurarse de SciPy está instalado, Python ejecuta en su terminal y tratar de importar SciPy:

>>> import scipy
>>> print(scipy.__file__)
/.../lib/python3.7/site-packages/scipy/__init__.py

En este código, que haya importado scipy e impreso la ubicación del archivo desde donde se carga scipy. El ejemplo anterior es para MacOS. El ordenador mostrará probablemente un lugar diferente. Ahora usted tiene SciPy instalado en su computadora lista para su uso. Puede pasar directamente a la siguiente sección para empezar a utilizar SciPy!

Pip

Si ya tiene una versión de Python instalado que no es Anaconda, o que no quieren utilizar Anaconda, entonces usted va a utilizar para instalar pip SciPy. Para aprender más acerca de lo que es pip, echa un vistazo a ¿Qué es la pipa? Una guía para Nueva Pythonistas.

Nota: pip instala los paquetes utilizando un formato llamado ruedas . En el formato de la rueda, el código se compila antes de que sea enviada a su ordenador. Esto es casi el mismo enfoque que toma Anaconda, aunque los archivos de formato de las ruedas son ligeramente diferentes que el formato Anaconda, y los dos no son intercambiables.

Para instalar SciPy usando pip, abra la aplicación de terminal y escriba la siguiente línea de código:

$ python -m pip install -U scipy

El código instalará SciPy si no está ya instalado, o actualizar SciPy si está instalado. Para asegurarse de SciPy está instalado, Python ejecuta en su terminal y tratar de importar SciPy:

>>> import scipy
>>> print(scipy.__file__)
/.../lib/python3.7/site-packages/scipy/__init__.py

En este código, que haya importado scipy e impreso la ubicación del archivo desde donde se carga scipy. El ejemplo anterior es para MacOS utilizando pyenv. El ordenador mostrará probablemente un lugar diferente. Ahora usted tiene SciPy instalado en su ordenador. Vamos a ver cómo se puede utilizar SciPy para resolver un par de problemas que pueden surgir!

Uso del módulo Cluster en SciPy

La agrupación es una técnica popular para categorizar los datos mediante la asociación en grupos. La biblioteca SciPy incluye una implementación de la k-medias algoritmo de agrupamiento así como varios algoritmos de agrupación jerárquica. En este ejemplo, podrás utilizar las k-medias algoritmo en scipy.cluster.vq, donde VQ representa cuantificación vectorial .

primer lugar, usted debe echar un vistazo a la base de datos que va a utilizar para este ejemplo. El conjunto de datos consta de 4827 reales y 747 de texto de spam (o SMS). El conjunto de datos en bruto se puede encontrar en la UCI Machine Learning repositorio o la página web de los autores.

Nota: Los datos fueron recogidos por Tiago A. Almeida y José María Gómez Hidalgo y publicados en un artículo titulado “Contribución al estudio de los SMS de filtrado de spam: Nueva colección y Resultados” en el Actas del Simposio ACM 2011 Documento de Ingeniería (DOCENG’11) sede en Mountain View, California, EE.UU. en 2011.

en el conjunto de datos, cada mensaje tiene una de dos etiquetas:

jamón para los mensajes legítimos

correo no deseado para correo no deseado mensajes

El mensaje de texto completo está asociado con cada etiqueta. Al escanear a través de los datos, se puede notar que los mensajes de spam tienden a tener una gran cantidad de dígitos numéricos en ellos. A menudo incluyen un número de teléfono o el premio ganancias. Vamos a predecir si un mensaje es spam basado en el número de dígitos en el mensaje. Para ello, se le cúmulo los datos en tres grupos en función del número de dígitos que aparecen en el mensaje:

No spam: Los mensajes con el menor número de dígitos no se predicen para ser spam.

Desconocido: mensajes con un número intermedio de dígitos son desconocidos y necesidad de ser procesado por algoritmos más avanzados.

Spam: Los mensajes con el mayor número de dígitos se prevé que sea correo no deseado. get de

Let comenzó con la agrupación de los mensajes de texto. En primer lugar, debe importar las bibliotecas que utilizará en este ejemplo:

1 from pathlib import Path
2 import numpy as np
3 from scipy.cluster.vq import whiten, kmeans, vq

Se puede ver que va a importar tres funciones de scipy.cluster.vq. Cada una de estas funciones acepta un array NumPy como entrada. Estas matrices deben tener el cuenta del conjunto de datos en las columnas y las observaciones en las filas.

Una característica es una variable de interés, mientras se crea una observación cada vez que se graba cada función. En este ejemplo, hay 5.574 observaciones, o mensajes individuales, en el conjunto de datos. Además, se verá que hay dos características:

A continuación, debe cargar el archivo de datos de la base de la UCI. Los datos se presenta como un archivo de texto, donde la clase del mensaje se separa del mensaje por un carácter de tabulación, y cada mensaje es en su propia línea. Debe leer los datos en una lista utilizando pathlib.Path:

4 data = Path("SMSSpamCollection").read_text()
5 data = data.strip()
6 data = data.split("\n")

En este código, se utiliza pathlib.Path.read_text () para leer el archivo en una cadena. A continuación, utiliza .strip () para eliminar cualquier espacio final y dividir la cadena en una lista con .split ().

A continuación, puede empezar a analizar los datos. Es necesario para contar el número de dígitos que aparecen en cada mensaje de texto. Python incluye collections.Counter en la biblioteca estándar para recoger el recuento de objetos en un diccionario-como la estructura. Sin embargo, ya que todas las funciones en scipy.cluster.vq esperan matrices NumPy como entrada, no se puede utilizar collections.Counter para este ejemplo. En su lugar, se utiliza una matriz NumPy e implementar el recuento manual.

Una vez más, usted está interesado en el número de dígitos en un mensaje SMS dado, y el número de mensajes SMS tienen ese número de dígitos. En primer lugar, se debe crear una matriz NumPy que se asocia el número de dígitos en un mensaje dado con el resultado del mensaje, si era el jamón o el correo no deseado:

7 digit_counts = np.empty((len(data), 2), dtype=int)

En este código, que está creando una matriz NumPy vacío, digit_counts, que tiene dos columnas y 5.574 filas. El número de filas es igual al número de mensajes en el conjunto de datos. Usted va a utilizar digit_counts asociar el número de dígitos en el mensaje con si o no el mensaje era spam.

Debe crear la matriz antes de entrar en el bucle, por lo que no tiene que asignar la nueva memoria como sus expande la matriz. Esto mejora la eficiencia de su código. A continuación, se debe procesar los datos para registrar el número de dígitos y el estado del mensaje:

8 for i, line in enumerate(data):
9 case, message = line.split("\t")
10 num_digits = sum(c.isdigit() for c in message)
11 digit_counts[i, 0] = 0 if case == "ham" else 1
12 digit_counts[i, 1] = num_digits

He aquí un desglose de línea por línea de cómo funciona este código:

  • Línea 8: Bucle sobre los datos. Se utiliza enumerate () para poner el valor de la lista en línea y crear un índice i para esta lista. Para obtener más información sobre enumerate (), echa un vistazo uso de enumeración () para mantener un índice de carrera.
  • Línea 9: Dividir la línea en el carácter de tabulación para crear el caso y el mensaje. caso es una cadena que dice si el mensaje es el jamón o el correo no deseado, mientras que el mensaje es una cadena con el texto del mensaje.
  • Línea 10: Calcular el número de dígitos en el mensaje mediante el uso de la suma () de una comprensión. En la comprensión, se comprueba cada carácter en el mensaje utilizando isdigit (), que devuelve verdadero si el elemento es un numeral y False en caso contrario. sum () y luego trata a cada resultado como una verdadera 1 y cada Falso como un 0. Por lo tanto, el resultado de la suma () en esta comprensión es el número de caracteres para los que isdigit () retorna true.
  • Línea 11: Asignar valores en digit_counts. Se asigna la primera columna de la fila i sea 0 si el mensaje era legítima (jamón) o 1 si el mensaje era spam.
  • Línea 12: Asignar valores en digit_counts. Se asigna la segunda columna de la fila i ser el número de dígitos en el mensaje.

Línea 8: bucle sobre los datos. Se utiliza enumerate () para poner el valor de la lista en línea y crear un índice i para esta lista. Para obtener más información sobre enumerate (), echa un vistazo uso de enumeración () para mantener un índice de carrera.

Línea 9: dividir la línea en el carácter de tabulación para crear el caso y el mensaje. caso es una cadena que dice si el mensaje es el jamón o el correo no deseado, mientras que el mensaje es una cadena con el texto del mensaje.

Línea 10: Calcular el número de dígitos en el mensaje mediante la suma () de una comprensión. En la comprensión, se comprueba cada carácter en el mensaje utilizando isdigit (), que devuelve verdadero si el elemento es un numeral y False en caso contrario. sum () y luego trata a cada resultado como una verdadera 1 y cada Falso como un 0. Por lo tanto, el resultado de la suma () en esta comprensión es el número de caracteres para los que isdigit () retorna true.

Línea 11: Los valores de Asignar en digit_counts. Se asigna la primera columna de la fila i sea 0 si el mensaje era legítima (jamón) o 1 si el mensaje era spam.

Línea 12: Los valores de Asignar en digit_counts. Se asigna la segunda columna de la fila i ser el número de dígitos en el mensaje.

Ahora usted tiene una matriz NumPy que contiene el número de dígitos en cada mensaje. Sin embargo, desea aplicar el algoritmo de agrupamiento a una matriz que tiene el número de mensajes con un cierto número de dígitos. En otras palabras, es necesario crear una matriz en donde la primera columna tiene el número de dígitos en un mensaje, y la segunda columna es el número de mensajes que tienen ese número de dígitos. Mira el código de abajo:

13 unique_counts = np.unique(digit_counts[:, 1], return_counts=True)

np.unique () toma una matriz como primer argumento y regresa otra matriz con los elementos únicos de la discusión. También tiene varios argumentos opcionales. En este caso, se utiliza return_counts = true para instruir np.unique () para devolver también una matriz con el número de veces que cada elemento único está presente en la matriz de entrada. Estas dos salidas se devuelven como una tupla que se almacenan en unique_counts.

Después, usted necesita para transformar unique_counts en una forma que es adecuada para la agrupación:

14 unique_counts = np.transpose(np.vstack(unique_counts))

se combinan las dos salidas de 1xN np.unique () en una matriz usando 2xN np.vstack (), y luego trasladarlas a un NX2 formación. Este formato es lo que vamos a usar en las funciones de agrupamiento. Cada fila de unique_counts ahora tiene dos elementos:

Un subconjunto de la salida de estas dos operaciones se muestra a continuación:

[[ 0 4110]
[ 1 486]
[ 2 160]
...
[ 40 4]
[ 41 2]
[ 47 1]]

En el conjunto de datos, hay 4110 mensajes que no tienen dígitos, 486 que tienen 1 dígitos, y así sucesivamente. Ahora, usted debe aplicar los kmeans algoritmo de agrupamiento a esta matriz:

15 whitened_counts = whiten(unique_counts)
16 codebook, _ = kmeans(whitened_counts, 3)

Usted uso blanquear () para normalizar cada característica de tener variación de la unidad, lo que mejora los resultados de kmeans (). Entonces, kmeans () toma los datos de blanqueado y el número de grupos para crear como argumentos. En este ejemplo, desea crear 3 grupos, por definitivamente jamón , definitivamente el spam y desconocida . kmeans () devuelve dos valores: array

Una con tres filas y dos columnas que representan los centroides de cada grupo: Los kmeans () algoritmo calcula la ubicación óptima del centroide de cada grupo, reduciendo al mínimo la distancia desde las observaciones a cada centroide. Esta matriz se asigna a libro de códigos.

La distancia euclidiana media de las observaciones a los centroides: no será necesario que el valor para el resto de este ejemplo, por lo que se puede asignar a _.

A continuación, debe determinar qué agruparse cada observación pertenece a mediante el uso de vq ():

17 codes, _ = vq(unique_counts, codebook)

VQ () asigna los códigos del libro de códigos a cada observación. Se devuelve dos valores:

El primer valor es una matriz de la misma longitud que unique_counts, donde el valor de cada elemento es un entero que representa la cual se agrupan que la observación se asigna a. Desde que utilizó tres grupos en este ejemplo, cada observación se asigna a clúster 0, 1, o 2.

El segundo valor es una matriz de la distancia euclidiana entre cada observación y su centroide.

Ahora que tiene los datos agrupados, se debe utilizar para hacer predicciones acerca de los mensajes SMS. Puede inspeccionar las cuentas para determinar en cuántos dígitos del algoritmo de agrupamiento dibujó la línea entre definitivamente jamón y desconocida, y entre desconocidos y sin duda spam:

18 print(unique_counts[codes == 0][-1])
19 print(unique_counts[codes == 1][-1])
20 print(unique_counts[codes == 2][-1])

En este código, cada línea es cada vez las filas de unique_counts donde asignado VQ () diferentes valores de los códigos, ya sea 0, 1 ó 2. Dado que la operación devuelve una matriz, debe obtener la última fila de la matriz para determinar el mayor número de dígitos asignados a cada grupo. La salida se muestra a continuación:

definitely spam [47 1]
definitely ham [ 0 4110]
unknown [20 18]

En esta salida, se ve que el definitivamente jamón mensajes son los mensajes con cero dígitos en el mensaje, los desconocidos mensajes son todo entre 1 y 20 dígitos, y definitivamente el spam los mensajes son todo, desde 21 hasta 47 dígitos, que es el número máximo de dígitos en el conjunto de datos.

Ahora, usted debe comprobar la forma precisa sus predicciones son en este conjunto de datos. En primer lugar, crear algunas máscaras para digit_counts para que pueda agarrar fácilmente el estado de jamón o spam de los mensajes:

21 digits = digit_counts[:, 1]
22 predicted_hams = digits == 0
23 predicted_spams = digits > 20
24 predicted_unknowns = np.logical_and(digits > 0, digits <= 20)

En este código, que está creando los predicted_hams máscara, donde no hay dígitos en un mensaje. A continuación, crear los predicted_spams enmascaran para todos los mensajes con más de 20 dígitos. Por último, los mensajes en el centro son predicted_unknowns.

A continuación, se aplican estas máscaras con los recuentos reales dígitos para recuperar las predicciones:

25 spam_cluster = digit_counts[predicted_spams]
26 ham_cluster = digit_counts[predicted_hams]
27 unk_cluster = digit_counts[predicted_unknowns]

Aquí, va a aplicar las máscaras que ha creado en el último bloque de código a la matriz digit_counts. Esto crea tres nuevas matrices con sólo los mensajes que han sido agrupadas en cada grupo. Por último, se puede ver cuántos de cada tipo de mensaje han caído en cada grupo:

28 print("hams:", np.unique(ham_cluster[:, 0], return_counts=True))
29 print("spams:", np.unique(spam_cluster[:, 0], return_counts=True))
30 print("unknowns:", np.unique(unk_cluster[:, 0], return_counts=True))

Este código imprime los cargos de cada valor único de los racimos. Recuerde que 0 significa que un mensaje ha sido jamón y 1 significa que el mensaje era spam. Los resultados se muestran a continuación:

hams: (array([0, 1]), array([4071, 39]))
spams: (array([0, 1]), array([ 1, 232]))
unknowns: (array([0, 1]), array([755, 476]))

De esta salida, se puede ver que los mensajes de 4110 cayeron en el definitivamente jamón grupo, de los cuales 4071 eran en realidad jamón y sólo 39 eran spam. Por el contrario, de los 233 mensajes que cayeron en la definitivamente el spam grupo , a sólo 1 fue en realidad el jamón y el resto eran spam.

Por supuesto, más de 1200 mensajes cayó en la categoría desconocido, por lo que sería necesario un análisis más avanzado para clasificar los mensajes. Es posible que desee ver en algo así como el procesamiento del lenguaje natural para ayudar a mejorar la precisión de la predicción, y se puede utilizar Python y Keras para ayudar.

Uso del módulo Optimizar en SciPy

Cuando necesite optimizar la los parámetros de entrada para una función, scipy. optimizar contiene una serie de métodos útiles para la optimización de diferentes tipos de funciones: minimize_scalar

  • () y minimizar () para minimizar una función de una variable y muchas variables, respectivamente
  • curve_fit () para adaptarse a una función a un conjunto de los datos
  • root_scalar () y raíz () para encontrar los ceros de una función de una variable y de muchas variables, respectivamente
  • linprog () para minimizar una función objetivo lineal con la desigualdad y la igualdad de restricciones lineales

En la práctica, todos de estas funciones están realizando optimización de un tipo u otro. En esta sección, usted aprenderá acerca de las dos funciones de minimización, minimize_scalar () y reducir al mínimo ().

minimizar una función con una variable

una función matemática que acepta un número y los resultados en una salida se llama una función escalar . Por lo general es contrastada con funciones multivariantes que aceptan varios números y también dan lugar a varios números de salida. Usted verá un ejemplo de optimización de las funciones multivariantes en la siguiente sección.

Para esta sección, su función escalar será un cuártica polinomio, y su objetivo es encontrar el valor mínimo de la función. La función es y = 3x⁴ - 2x + 1. La función se representa en la siguiente imagen para una serie de x de 0 a 1:

En la figura, se puede ver que hay un valor mínimo de esta función en aproximadamente x = 0,55. Puede utilizar minimize_scalar () para determinar las exactas x y coordenadas xey del mínimo. En primer lugar, minimize_scalar importación () desde scipy.optimize. Entonces, es necesario definir la función objetivo a minimizar:

1 from scipy.optimize import minimize_scalar
2
3 def objective_function(x):
4 return 3 * x ** 4 - 2 * x + 1

objective_function () toma la entrada x y aplica las operaciones matemáticas necesarias para que, a continuación, devuelve el resultado. En la definición de la función, se puede utilizar cualquier función matemática deseada. El único límite es que la función debe devolver un solo número al final.

A continuación, el uso minimize_scalar () para encontrar el valor mínimo de esta función.

5 res = minimize_scalar(objective_function)

La salida del minimize_scalar () es una instancia de OptimizeResult: minimize_scalar () sólo tiene una entrada, que es el nombre de la definición de la función objetivo requerido. Esta clase reúne a muchos de los detalles relevantes de la carrera del optimizador, incluyendo si o no la optimización se ha realizado correctamente y, si tiene éxito, ¿cuál fue el resultado final. La salida del minimize_scalar () para esta función se muestra a continuación:

fun: 0.17451818777634331
nfev: 16
nit: 12
success: True
x: 0.5503212087491959

Estos resultados son todos los atributos de OptimizeResult. el éxito es un valor booleano que indica si o no la optimización completada con éxito. Si la optimización se ha realizado correctamente, entonces la diversión es el valor de la función objetivo en el valor óptimo de x. Se puede ver en la salida que, como era de esperar, el valor óptimo para esta función estaba cerca de x = 0,55.

Nota: Como ya sabrán, no cada función tiene un mínimo . Por ejemplo, tratar de ver lo que sucede si su función objetivo es y = x ³. Para minimize_scalar (), funciones objetivo con ningún mínimo a menudo resultan en una OverflowError porque el optimizador finalmente intentó el número que es demasiado grande para ser calculada por el ordenador.

En el lado opuesto de funciones sin mínimo son funciones que tienen varios mínimos . En estos casos, minimize_scalar () no está garantizado para encontrar el mínimo global de la función. Sin embargo, minimize_scalar () tiene un argumento de palabra clave método que se puede especificar para controlar el programa de solución que se utiliza para la optimización. La biblioteca SciPy tiene tres métodos integrados para la minimización de escalar:

Cuando método es bien Brent o dorado, minimize_scalar () toma otro argumento llamado soporte. Esta es una secuencia de dos o tres elementos que proporcionan una aproximación inicial para los límites de la región con el mínimo. Sin embargo, estos solucionadores no garantizan que el mínimo se encontró estará dentro de este rango.

Por otro lado, cuando está delimitada método, minimize_scalar () toma otro argumento denominado límites. Esta es una secuencia de dos elementos que estrictamente ligadas la región de búsqueda para el mínimo. Pruebe el método acotado con la función y = X $ ⁴ $ - x². Esta función se representa en la figura siguiente:

Utilizando el código de ejemplo anterior, se puede redefinir objective_function (), así:

7 def objective_function(x):
8 return x ** 4 - x ** 2

En primer lugar, intente el método de Brent por defecto:

9 res = minimize_scalar(objective_function)

En este código, no lo hiciste t pasar un valor para el método, por lo minimize_scalar () utiliza el método de Brent por defecto. La salida es la siguiente:

fun: -0.24999999999999994
nfev: 15
nit: 11
success: True
x: 0.7071067853059209

Se puede ver que la optimización se ha realizado correctamente. Se encontró que la óptima cerca de x = 0,707 e Y = -1/4. Si usted ha resuelto por el mínimo de la ecuación analíticamente, a continuación, que iba a encontrar el mínimo en x = 1 / √2, que está muy cerca de la respuesta encontrada por la función de minimización. Sin embargo, lo que si se quería encontrar el mínimo simétrica en x = -1 / √2? Puede devolver el mismo resultado, proporcionando el argumento de soporte al método de Brent:

10 res = minimize_scalar(objective_function, bracket=(-1, 0))

En este código, se proporciona la secuencia (-1, 0) en el soporte para iniciar la búsqueda en la región entre -1 y 0. Espera que haya un mínimo en esta región desde la función objetivo es simétrica sobre el eje y. Sin embargo, incluso con el soporte, el método Brent todavía devuelve el mínimo en x = + 1 / √2. Para encontrar el mínimo en x = -1 / √2, puede utilizar el método acotado con límites:

11 res = minimize_scalar(objective_function, method='bounded', bounds=(-1, 0))

En este código, se agrega método y límites como argumentos a minimize_scalar (), y establece límites a ser de -1 a 0. la salida de este método es como sigue:

fun: -0.24999999999998732
message: 'Solution found.'
nfev: 10
status: 0
success: True
x: -0.707106701474177

como se esperaba, el mínimo fue encontrado en x = -1 / √2. Nota la producción adicional de este método, que incluye un atributo de mensaje en res. Este campo se utiliza a menudo para la salida más detallado de algunos de los solucionadores de minimización.

minimizar una función con muchas variables

scipy.optimize también incluye el más general minimizar (). Esta función puede manejar entradas y salidas multivariante y tiene más complicado algoritmos de optimización para ser capaz de manejar esto. Además, minimizar () puede manejar las limitaciones en la solución a su problema. Puede especificar tres tipos de restricciones :

Al utilizar estas limitaciones, se puede limitar la elección específica del método de optimización que es capaz de utilizar, ya que no todos los métodos disponibles apoyan las limitaciones de esta manera.

vamos a probar una demostración sobre el uso de minimizar (). Imagínese que usted es un corredor de bolsa que esté interesado en maximización de los ingresos totales de la venta de un número fijo de sus acciones. Que haya identificado un conjunto particular de los compradores, y para cada comprador, saber el precio que tendrá que pagar y la cantidad de dinero que tienen a mano.

Usted frase puede este problema como un problema de optimización restringida . La función objetivo es que desea maximizar sus ingresos. Sin embargo, reducir al mínimo () Busca el valor mínimo de una función, por lo que necesita para multiplicar su función objetivo por -1 para encontrar los valores de x que producen el mayor número negativo.

Hay una limitación en el problema, que es que la suma del total de acciones adquiridas por los compradores no exceda el número de acciones que tiene a mano. También hay delimita en cada una de las variables de la solución, ya que cada comprador tiene un límite superior de efectivo disponible, y un límite inferior de cero. Solution X-valores negativos significan que usted estaría pagando los compradores!

Pruebe el siguiente código para resolver este problema. En primer lugar, la importación de los módulos que necesite y variables a continuación, establecidos para determinar el número de compradores en el mercado y el número de acciones que desea vender:

1 import numpy as np
2 from scipy.optimize import minimize, LinearConstraint
3
4 n_buyers = 10
5 n_shares = 15

En este código, se importa numpy, minimizar (), y LinearConstraint de scipy. optimizar. A continuación, se establece un mercado de 10 compradores que va a comprar 15 acciones en total de usted.

A continuación, crear matrices para almacenar el precio que cada comprador paga, la cantidad máxima que pueden permitirse el lujo de gastar, y el número máximo de acciones que cada comprador puede permitirse, dado los primeros dos matrices. Para este ejemplo, puede utilizar la generación de números aleatorios en np.random para generar las matrices:

6 np.random.seed(10)
7 prices = np.random.random(n_buyers)
8 money_available = np.random.randint(1, 4, n_buyers)

En este código, establecer la semilla para los generadores de números aleatorios de NumPy. Esta función se asegura de que cada vez que se ejecuta este código, se obtendrá el mismo conjunto de números aleatorios. Es aquí para asegurarse de que su salida es el mismo que el tutorial para la comparación.

En la línea 7, que genera el conjunto de los precios de los compradores pagarán. np.random.random () crea una matriz de números aleatorios en el intervalo semiabierto [0, 1). El número de elementos de la matriz se determina por el valor del argumento, que en este caso es el número de compradores.

En la línea 8, se genera una matriz de enteros en el intervalo semiabierto de [1, 4), de nuevo con el tamaño del número de compradores. Esta matriz representa el total de efectivo cada comprador tiene disponible. Ahora, es necesario calcular el número máximo de acciones que cada comprador puede comprar:

9 n_shares_per_buyer = money_available / prices
10 print(prices, money_available, n_shares_per_buyer, sep="\n")

En la línea 9, se toma la relación de la money_available con los precios para determinar el número máximo de acciones que cada comprador puede adquirir. Por último, se imprime cada una de estas matrices separadas por un salto de línea. La salida se muestra a continuación:

[0.77132064 0.02075195 0.63364823 0.74880388 0.49850701 0.22479665
0.19806286 0.76053071 0.16911084 0.08833981]
[1 1 1 3 1 3 3 2 1 1]
[ 1.29647768 48.18824404 1.57816269 4.00638948 2.00598984 13.34539487
15.14670609 2.62974258 5.91328161 11.3199242 ]

La primera fila es la gama de precios, que son números de punto flotante entre 0 y 1. Esta fila es seguido por el máximo de efectivo disponible en números enteros de 1 a 4. Por último, se ve la número de acciones que cada comprador puede adquirir.

Ahora, es necesario crear las limitaciones y límites para el solucionador. La restricción es que la suma total de las acciones comprada no puede exceder el número total de acciones disponibles. Esta es una limitación en lugar de un límite, ya que implica más de una de las variables de la solución.

To represent this mathematically, you could say that x[0] + x[1] + ... + x[n] = n_shares, where n is the total number of buyers. More succinctly, you could take the dot or inner product of a vector of ones with the solution values, and constrain that to be equal to n_shares. Remember that LinearConstraint takes the dot product of the input array with the solution values and compares it to the lower and upper bound. You can use this to set up the constraint on n_shares:

11 constraint = LinearConstraint(np.ones(n_buyers), lb=n_shares, ub=n_shares)

In this code, you create an array of ones with the length n_buyers and pass it as the first argument to LinearConstraint. Since LinearConstraint takes the dot product of the solution vector with this argument, it’ll result in the sum of the purchased shares.

This result is then constrained to lie between the other two arguments:

Since lb = ub = n_shares, this is an equality constraint because the sum of the values must be equal to both lb and ub. If lb were different from ub, then it would be an in equality constraint .

Next, create the bounds for the solution variable. The bounds limit the number of shares purchased to be 0 on the lower side and n_shares_per_buyer on the upper side. The format that minimize() expects for the bounds is a sequence of tuples of lower and upper bounds:

12 bounds = [(0, n) for n in n_shares_per_buyer]

In this code, you use a comprehension to generate a list of tuples for each buyer. The last step before you run the optimization is to define the objective function. Recall that you’re trying to maximize your income. Equivalently, you want to make the negative of your income as large a negative number as possible.

The income that you generate from each sale is the price that the buyer pays multiplied by the number of shares they’re buying. Mathematically, you could write this as prices[0]*x[0] + prices[1]*x[1] + ... + prices[n]*x[n], where n is again the total number of buyers.

Once again, you can represent this more succinctly with the inner product, or x.dot(prices). This means that your objective function should take the current solution values x and the array of prices as arguments:

13 def objective_function(x, prices):
14 return -x.dot(prices)

In this code, you define objective_function() to take two arguments. Then you take the dot product of x with prices and return the negative of that value. Remember that you have to return the negative because you’re trying to make that number as small as possible, or as close to negative infinity as possible. Finally, you can call minimize():

15 res = minimize(
16 objective_function,
17 x0=10 * np.random.random(n_buyers),
18 args=(prices,),
19 constraints=constraint,
20 bounds=bounds,
21 )

In this code, res is an instance of OptimizeResult, just like with minimize_scalar(). As you’ll see, there are many of the same fields, even though the problem is quite different. In the call to minimize(), you pass five arguments:

objective_function : The first positional argument must be the function that you’re optimizing.

x0 : The next argument is an initial guess for the values of the solution. In this case, you’re just providing a random array of values between 0 and 10, with the length of n_buyers. For some algorithms or some problems, choosing an appropriate initial guess may be important. However, for this example, it doesn’t seem too important.

args : The next argument is a tuple of other arguments that are necessary to be passed into the objective function. minimize() will always pass the current value of the solution x into the objective function, so this argument serves as a place to collect any other input necessary. In this example, you need to pass prices to objective_function(), so that goes here.

constraints : The next argument is a sequence of constraints on the problem. You’re passing the constraint you generated earlier on the number of available shares.

bounds : The last argument is the sequence of bounds on the solution variables that you generated earlier.

Once the solver runs, you should inspect res by printing it:

fun: -8.783020157087366
jac: array([-0.77132058, -0.02075195, -0.63364816, -0.74880385,
-0.4985069, -0.22479665, -0.19806278, -0.76053071, -0.16911077,
-0.08833981])
message: 'Optimization terminated successfully.'
nfev: 204
nit: 17
njev: 17
status: 0
success: True
x: array([1.29647768e+00, 3.94665456e-13, 1.57816269e+00, 4.00638948e+00,
2.00598984e+00, 3.48323773e+00, 5.55111512e-14, 2.62974258e+00,
5.37143977e-14, 1.34606983e-13])

In this output, you can see message and status indicating the final state of the optimization. For this optimizer, a status of 0 means the optimization terminated successfully, which you can also see in the message. Since the optimization was successful, fun shows the value of the objective function at the optimized solution values. You’ll make an income of $8.78 from this sale.

You can see the values of x that optimize the function in res.x. In this case, the result is that you should sell about 1.3 shares to the first buyer, zero to the second buyer, 1.6 to the third buyer, 4.0 to the fourth, and so on.

You should also check and make sure that the constraints and bounds that you set are satisfied. You can do this with the following code:

22 print("The total number of shares is:", sum(res.x))
23 print("Leftover money for each buyer:" money_available - res.x * prices)

In this code, you print the sum of the shares purchased by each buyer, which should be equal to n_shares. Then, you print the difference between each buyer’s cash on hand and the amount they spent. Each of these values should be positive. The output from these checks is shown below:

The total number of shares is: 15.0
The amount each buyer has leftover is: [4.78506124e-14 1.00000000e+00
4.95159469e-14 9.99200722e-14 5.06261699e-14 2.21697984e+00 3.00000000e+00
9.76996262e-14 1.00000000e+00 1.00000000e+00]

As you can see, all of the constraints and bounds on the solution were satisfied. Now you should try changing the problem so that the solver can’t find a solution. Change n_shares to a value of 1000, so that you’re trying to sell 1000 shares to these same buyers. When you run minimize(), you’ll find that the result is as shown below:

fun: nan
jac: array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])
message: 'Iteration limit exceeded'
nfev: 2160
nit: 101
njev: 100
status: 9
success: False
x: array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])

Notice that the status attribute now has a value of 9, and the message states that the iteration limit has been exceeded. There’s no way to sell 1000 shares given the amount of money each buyer has and the number of buyers in the market. However, rather than raising an error, minimize() still returns an OptimizeResult instance. You need to make sure to check the status code before proceeding with further calculations.

Conclusion

In this tutorial, you learned about the SciPy ecosystem and how that differs from the SciPy library . You read about some of the modules available in SciPy and learned how to install SciPy using Anaconda or pip. Then, you focused on some examples that use the clustering and optimization functionality in SciPy.

In the clustering example, you developed an algorithm to sort spam text messages from legitimate messages. Using kmeans(), you found that messages with more than about 20 digits are extremely likely to be spam!

In the optimization example, you first found the minimum value in a mathematically clear function with only one variable. Then, you solved the more complex problem of maximizing your profit from selling stocks. Using minimize(), you found the optimal number of stocks to sell to a group of buyers and made a profit of $8.79!

SciPy is a huge library, with many more modules to dive into. With the knowledge you have now, you’re well equipped to start exploring!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *