Instalar ssh en Windows 10


Hace ya tres años, Microsoft presentó WSL, lo que son las siglas de Windows Susbystem for Linux. Como usuario de Ubuntu pensé «Esto no sirve para nada, no lo voy a usar nunca si ya uso Ubuntu de nativo», pero ¿estaba en lo cierto? Probablemente no. Justamente he empezado a usar WSL en Windows 10 porque soy usuario de Linux, porque el terminal de Ubuntu nos ofrece posibilidades muy interesantes que merece la pena tener a mano.

Lógicamente, no es perfecto. Tal y como explicaremos a continuación, habrá algunas tareas que no podamos realizar, en parte porque lo que vamos a instalar y usar es solo un terminal, es decir, una ventana en la que introduciremos las líneas de comandos para hacer lo que necesitemos. A continuación os explico los pasos a seguir para instalar el terminal de Ubuntu 18.04 en Windows 10 y qué podemos hacer con él.

Índice [Ocultar]

WSL, ejecutando comandos de Linux en Windows 10

Antes de poder usarlo, tenemos que instalarlo. Los pasos a seguir serían los siguientes:

  1. Vamos a la Microsoft Store e instalamos Ubuntu 18.04.
Instalar Ubuntu 18.04 desde la Microsoft Store
  1. A continuación, tenemos que ejecutar como administrador el siguiente comando. Para ello, hacemos clic derecho sobre Inicio y elegimos «Windows PowerShell (Administrator)»:(boton derecho como administrador)
1Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Activar WSL
  1. Esperamos a que se active WSL. Una vez finalizado el proceso, tenemos que reiniciar. Por defecto, está marcado que «sí», por lo que podemos reiniciar presionando Intro. También podemos hacerlo los primeros pasos al contrario: activar primero WSL y luego instalar Ubuntu.
Instalando WSL
  1. A continuación, iniciamos Ubuntu desde el menú de aplicaciones.
  2. Esperamos un rato a que se instale el sistema.
Esperamos a que se instale el sistema
  1. Llegado el momento, nos pedirá un nombre de usuario. Tenemos que introducirlo en minúsculas y presionar Intro.
  2. Para la contraseña, haremos lo mismo que en cualquier otra parte: ponerla una vez, presionar intro, ponerla otra vez para confirmarla y volver a presionar Intro.
Introducir usuario y contraseña

Y eso sería todo. Ya tenemos el terminal de Ubuntu instalado en Windows. Por defecto ya podemos usar comandos como el APT, por lo que la primera prueba que recomiendo es instalar «neofetch»:

1sudo apt install neofetch

Para lanzarlo y ver algo como lo de la imagen de cabecera, solo tenéis que escribir «neofetch» sin las comillas. Me parece importante mencionar que podemos lanzar los comandos de Linux desde el PowerShell de Windows o directamente desde la opción «Ejecutar«.

Qué podemos y qué no podemos hacer con WSL

No funcionan programas con GUI en WSL

Lo que hay que tener claro es qué es un terminal. Explicado rápido y mal, es un sistema operativo que funciona única y exclusivamente con líneas de comandos y no puede mostrar imágenes más allá del texto que introducimos/muestra. Esto significa que, por ejemplo, podemos instalar cualquier programa que esté disponible en los repositorios de Ubuntu, pero no podremos lanzar aquellos que hagan uso de una GUI, como Firefox (aunque no tendría sentido instalar nada que esté disponible para Windows de manera oficial). También significa que no podremos seguir, por ejemplo, este tutorial para grabar la pantalla con ffmpeg: si introducimos el comando y presionamos Intro, empezará la tarea, pero parará cuando se dé cuenta de que «no hay ningún monitor disponible».

En el momento de escribir este artículo, tampoco es compatible con los paquetes Snap, por lo que no he podido probar un paquete que nos permite visualizar GIFs desde el terminal (probablemente escriba un artículo sobre él).

Pero ya que hemos mencionado ffmpeg, decir que sí podemos usarlo para convertir archivos, algo que explicamos en este otro artículo. Pero antes tenemos que instalar el software y todas sus dependencias (sudo apt install ffmpeg). También podemos instalar ImageMagick y hacer esto otro, lo que nos permitirá convertir/editar imágenes por lotes.

Pero hay un problemilla con las rutas…

Algo que me gustaría que solucionaran en el futuro está relacionado con las rutas. No son lo mismo y no las reconoce igual. El problema está en cómo las escribe Windows y cómo las necesita Linux. Lo bueno es que es fácil recordar cómo convertir una ruta de Windows a Linux.

Por ejemplo: la ruta C:\Users\Pablo\Destktop\ de Windows sería /mnt/c/Users/Pablo/Desktop. Sabiéndolo, si alguna vez queremos arrastrar un archivo de Windows al terminal de Ubuntu, lo que tenemos que hacer es básicamente cambiar las barras invertidas por barras normales, poner la «c» minúscula, quitar los dos puntos y delante añadir «/mnt/». No es difícil de recordar.

Y así es como se instala y usa WSL en Windows 10. Teniendo en cuenta la capacidad de los discos duros de los ordenadores actuales y las posibilidades que nos ofrece, creo que merece la pena tenerlo instalado. Y salgo del artículo con el siguiente comando:

exit

¿Que significa MLE?


Las siglas MLE corresponden al algoritmo de estimación de máxima verosimilitud y se usa por ejemplo para la desagregación de energía.

Es responsable cuando se desea un solo aparato desagregado en lugar de desagregar muchos. Además, el aparato debe ser mayoritariamente resistivo para lograr precisión.

Se basa en eventos emparejados:

- OnPower: valor delta cuando el aparato está encendido. 
- OffPOwer: valor delta cuando el aparato está apagado. 
- Duración: duración entre encendido y apagado.

Además, para descartar muchos eventos poco probables, se establecen tres restricciones:

- PowerNoise: valor delta mínimo por debajo del cual el delta se considera ruido. 
- PowerPair: diferencia máxima entre OnPower y OffPower (considerando electrodomésticos con consumo de energía constante).
 - timeWindow: marco de tiempo máximo entre Onpower y Offpower.

Las características antes mencionadas se modelan con gaussianas, mezclas gaussianas o Poisson. Para cada evento emparejado entrante, el algoritmo extraerá estas tres características y evaluará la probabilidad de máxima verosimilitud de que ese evento emparejado sea un dispositivo determinado.

IMPORTACIONES

import numpy as np
import pandas as pd
from os.path import join
from pylab import rcParams
import matplotlib.pyplot as plt
%matplotlib inline
rcParams['figure.figsize'] = (13, 6)
#plt.style.use('ggplot')
from datetime import datetime as datetime2
from datetime import timedelta

import nilmtk
from nilmtk.disaggregate.maximum_likelihood_estimation import MLE
from nilmtk import DataSet, TimeFrame, MeterGroup, HDFDataStore
from scipy.stats import poisson, norm
from sklearn import mixture
import warnings
warnings.filterwarnings("ignore")

Funciones

def get_all_appliances(appliance):

    # Filtering by appliances: 
    print "Fetching " + appliance + " over data loaded to nilmtk."
    metergroup = nilmtk.global_meter_group.select_using_appliances(type=appliance)
    
    if len(metergroup.appliances) == 0: 
        print "None " + appliance + " found on memory."
        pass

    # Selecting only single meters: 
    print "Filtering to get one meter for each " + appliance

    meters = [meter for meter in metergroup.meters if (len(meter.appliances) == 1)]
    metergroup = MeterGroup(meters)
    print metergroup
    print "Found " + str(len(metergroup.meters)) + " " + appliance

    return metergroup


def get_all_trainings(appliance, train):

    # Filtering by appliances: 
    print "Fetching " + appliance + " over data train data."
    elecs = []
    for building in train.buildings: 
        print "Building " + str(building) + "..."
        elec = train.buildings[building].elec[appliance]
        if len(elec.appliances) == 1: 
            print elec
            print "Fetched elec."
            elecs.append(elec)

        else: 
            print elec
            print "Groundtruth does not exist. Many appliances or None"

    metergroup = MeterGroup(elecs)

    return metergroup

Cargando datos

path = '../../../nilmtk/data/ukdale'
ukdale = train = DataSet(join(path, 'ukdale.h5'))

Y dividir en datos de prueba y de entrenaminento

In [8]:train = DataSet(join(path, 'ukdale.h5'))
test = DataSet(join(path, 'ukdale.h5'))
train.set_window(end="17-5-2013")
test.set_window(start="17-5-2013")
#zoom.set_window(start="17-5-2013")
print('loaded ' + str(len(ukdale.buildings)) + ' buildings')

loaded 5 buildings

Obteniendo los datos de entrenamiento

Es posible que el dispositivo seleccionado no esté entrenado desde ElecMeters donde se presentan otros dispositivos, ya que podemos extraer la verdad básica

# Appliance to disaggregate: 
applianceName = 'kettle'
# Groundtruth from the training data: 
metergroup = get_all_trainings(applianceName,train)

Fetching kettle over data train data.
Building 1...
ElecMeter(instance=10, building=1, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1), Appliance(type='food processor', instance=1), Appliance(type='toasted sandwich maker', instance=1)])
Groundtruth does not exist. Many appliances or None
Building 2...
ElecMeter(instance=8, building=2, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.
Building 3...
ElecMeter(instance=2, building=3, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.
Building 4...
ElecMeter(instance=3, building=4, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1), Appliance(type='radio', instance=1)])
Groundtruth does not exist. Many appliances or None
Building 5...
ElecMeter(instance=18, building=5, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.

Algoritmo MLE

Capacitación

Primero, creamos el modelo

mle = MLE()

Luego, actualizamos el parámetro del modelo con algunos valores de adivinación.

Primero adivine las características: mezclas gaussianas de encendido y apagado y poisson de duración.

# setting parameters in the model: 
mle.update(appliance=applianceName, resistive=True, units=('power','active'), thDelta= 1500, thLikelihood= 1e-10, powerNoise= 50, powerPair= 100, timeWindow= 400, sample_period= '10S', sampling_method='first')

# Settings the features parameters by guessing:  
mle.onpower = {'name':'gmm', 'model': mixture.GMM(n_components=2)}
mle.offpower = {'name':'gmm', 'model': mixture.GMM(n_components=2)}
mle.duration = {'name':'poisson', 'model': poisson(0)}

Updating model
{'resistive': True, 'appliance': 'kettle', 'sampling_method': 'first', 'sample_period': '10S', 'thLikelihood': 1e-10, 'timeWindow': 400, 'units': ('power', 'active'), 'thDelta': 1500, 'powerNoise': 50, 'powerPair': 100}

Entrenando el modelo

Entrenamos el modelo con todas las ocurrencias de ese modelo de dispositivo que se encuentran en los datos de entrenamiento.

mle.train(metergroup)

('kettle', 1)
Training on chunk
Samples of onpower: 214
Samples of offpower: 214
Samples of duration: 214
Training onpower
Training offpower
Training duration
('kettle', 2)
Training on chunk
Samples of onpower: 92
Samples of offpower: 92
Samples of duration: 92
Training onpower
Training offpower
Training duration
('kettle', 3)
Chunk empty

Y luego visualizamos características con featureHist_colors () para ver la distribución y cuántas muestras tenemos para cada dispositivo (el mismo modelo de diferentes casas).

mle.featuresHist_colors()


A veces, tenemos más eventos de algunas casas que de otras, como vemos en la figura de arriba. Por lo tanto, necesitamos recortar información para mantener el mismo número de muestras para cada casa.

mle.no_overfitting()

Retraining onpower
Retraining offpower
Retraining duration

In [15]:mle.featuresHist_colors()


Hay otra herramienta de visualización para ver cómo se ajustan las distribuciones del modelo a los datos:

mle.featuresHist()


Onpower y Offpower parecen encajar bien con los datos, pero necesitamos cambiar el modelo por duración

mle.duration = {'name':'gmm', 'model': mixture.GMM(n_components=10)}

Y luego volvemos a entrenar el modelo y usamos no_overfitting

mle.train(metergroup)
mle.no_overfitting()
mle.featuresHist()

('kettle', 1)
Training on chunk
Samples of onpower: 214
Samples of offpower: 214
Samples of duration: 214
Training onpower
Training offpower
Training duration
('kettle', 2)
Training on chunk
Samples of onpower: 92
Samples of offpower: 92
Samples of duration: 92
Training onpower
Training offpower
Training duration
('kettle', 3)
Chunk empty
Retraining onpower
Retraining offpower
Retraining duration

Una vez que tengamos la distribución del modelo final para cada característica. Necesitamos la integridad de cada distribución. Cada CDF debe estar delimitado por uno.

mle.check_cdfIntegrity(step=10)

Onpower cdf: 0.986177684776
Offpower cdf: 1.0
Duration cdf: 0.987375070732

Desagregación

# Building to disaggregate: 
building = 2
mains = test.buildings[building].elec.mains()

# File to store the disaggregation
filename= '/home/energos/Escritorio/ukdale-disag-ml.h5'
output = HDFDataStore(filename, 'w')

El siguiente paso tomará unos minutos.

mle.disaggregate(mains, output)

25656 events found.
12419 onEvents found
4244 onEvents no paired.
1 chunks disaggregated

También recibimos cierta información, como el número total de eventos, el número de eventos de encendido, el número de eventos que no se han emparejado y los fragmentos desglosados.

Comparando la desagregación con la verdad básica

## Groundtruth
kettle = test.buildings[building].elec.select_using_appliances(type=applianceName)
output.load(mains.key).next().plot()
kettle.plot()
output.close()