text:
# Basics with string sequence

• Find this notebook at EpyNN/epynnlive/dummy_string/train.ipynb.

• Regular python code at EpyNN/epynnlive/dummy_string/train.py.

Run the notebook online with Google Colab.

Level: Beginner

In this notebook we will review:

• Handling sequential string data.

• Training of Feed-Forward (FF) and recurrent networks (RNN, LSTM, GRU).

• Differences between decisions and probabilities and related functions.

It is assumed that all basics notebooks were already reviewed:

This notebook does not enhance, extend or replace EpyNN’s documentation.

Relevant documentation pages for the current notebook:

## Environment and data

Briefly, these dummy string data consist of sequences of characters. Sample features are each represented by one sequence and can be either associated with a positive or negative label.

Positive sequences are met when the first element in the sequence is equal to the last element in this same sequence, and reciprocally.

[1]:

# EpyNN/epynnlive/dummy_string/train.ipynb
# Install dependencies

# Standard library imports
import random

# Related third party imports
import numpy as np

# Local application/library specific imports
import epynn.initialize
from epynn.commons.io import one_hot_decode_sequence
from epynn.commons.maths import relu, softmax
from epynn.commons.library import (
configure_directory,
)
from epynn.network.models import EpyNN
from epynn.embedding.models import Embedding
from epynn.flatten.models import Flatten
from epynn.rnn.models import RNN
from epynn.gru.models import GRU
from epynn.lstm.models import LSTM
from epynn.dense.models import Dense
from epynnlive.dummy_string.prepare_dataset import prepare_dataset
from epynnlive.dummy_string.settings import se_hPars

########################## CONFIGURE ##########################
random.seed(1)

np.set_printoptions(threshold=10)

np.seterr(all='warn')

configure_directory()

############################ DATASET ##########################
X_features, Y_label = prepare_dataset(N_SAMPLES=480)

Let’s control what we retrieved.

[2]:

print(len(X_features))
print(len(X_features[0]))
print(X_features[0])
print(Y_label[0])

480
12
['G', 'A', 'C', 'T', 'T', 'G', 'G', 'C', 'C', 'A', 'T', 'C']
1

We retrieved a set of sample features describing 480 samples.

Each sample is described by 12 string features.

Herein the label is 1 because the first and last element are different.

## Feed-Forward (FF)

To compare Feed-Forward and recurrent networks, we are going to train a simple Perceptron first.

### Embedding

The principle of One-hot encoding of string features was detailed before.

Briefly, we can not do math on string data. Therefore, the one-hot encoding process may be summarized as such:

• List of all elements of size vocab_size. This basically answers: what is the number of distinct elements we can find in your data?

• Each element is associated with one index in the range(0, vocab_size). This provides an element_to_idx encoder.

• For one sample and for each element in the associated list of features, a zero array is initialized. This array is set to one at the index which is assigned to the element_to_idx encoder.

This is achieved during instantiation of the embedding layer by setting up X_encode=True.

[3]:

embedding = Embedding(X_data=X_features,
Y_data=Y_label,
X_encode=True,
Y_encode=True,
relative_size=(2, 1, 0))

Let’s inspect some properties.

[4]:

print(embedding.e2i)  # element_to_idx
print(embedding.dtrain.X[0])

print(embedding.i2e)  # idx_to_element
print(one_hot_decode_sequence(embedding.dtrain.X[0], embedding.i2e))

{'A': 0, 'C': 1, 'G': 2, 'T': 3}
[[0. 0. 1. 0.]
[1. 0. 0. 0.]
[0. 1. 0. 0.]
...
[1. 0. 0. 0.]
[0. 0. 0. 1.]
[0. 1. 0. 0.]]
{0: 'A', 1: 'C', 2: 'G', 3: 'T'}
['G', 'A', 'C', 'T', 'T', 'G', 'G', 'C', 'C', 'A', 'T', 'C']

Encoded sequences may be decoded as shown above.

### Flatten-Dense - Perceptron

Let’s inspect the shape of the data.

[5]:

print(embedding.dtrain.X.shape)

(320, 12, 4)

It contains 320 samples (m), each described by a sequence of 12 features (s) containing 4 elements (v).

12 features is the length of the sequences and 4 elements is the size of the vocabulary. Remember one-hot encoding makes a zero array of this size and sets 1 at the index corresponding to the element being encoded.

Still, the fully-connected or dense layer can only process bi-dimensional input arrays. That is the reason why we need to invoke a flatten layer in between the embedding and dense layer.

[6]:

name = 'Flatten_Dense-2-softmax'

se_hPars['learning_rate'] = 0.001

flatten = Flatten()

dense = Dense(2, softmax)

layers = [embedding, flatten, dense]

model = EpyNN(layers=layers, name=name)

Initialize using most classically a MSE or Binary Cross Entropy loss function.

[7]:

model.initialize(loss='BCE', seed=1, se_hPars=se_hPars.copy(), end='\r')

--- EpyNN Check OK! ---

Train for hundred epochs.

[8]:

model.train(epochs=50, init_logs=False)

Epoch 49 - Batch 0/0 - Accuracy: 0.738 Cost: 0.55582 - TIME: 2.14s RATE: 2.34e+01e/s TTC: 0s

+-------+----------+----------+-------+--------+-------+------------------------------------+
| epoch |  lrate   | accuracy |       |  BCE   |       |             Experiment             |
|       |  Dense   |  dtrain  | dval  | dtrain | dval  |                                    |
+-------+----------+----------+-------+--------+-------+------------------------------------+
|   0   | 1.00e-03 |  0.688   | 0.694 | 0.631  | 0.640 | 1635014418_Flatten_Dense-2-softmax |
|   5   | 1.00e-03 |  0.716   | 0.731 | 0.609  | 0.620 | 1635014418_Flatten_Dense-2-softmax |
|  10   | 1.00e-03 |  0.719   | 0.750 | 0.596  | 0.609 | 1635014418_Flatten_Dense-2-softmax |
|  15   | 1.00e-03 |  0.728   | 0.750 | 0.585  | 0.601 | 1635014418_Flatten_Dense-2-softmax |
|  20   | 1.00e-03 |  0.728   | 0.750 | 0.577  | 0.595 | 1635014418_Flatten_Dense-2-softmax |
|  25   | 1.00e-03 |  0.734   | 0.756 | 0.571  | 0.590 | 1635014418_Flatten_Dense-2-softmax |
|  30   | 1.00e-03 |  0.734   | 0.756 | 0.566  | 0.587 | 1635014418_Flatten_Dense-2-softmax |
|  35   | 1.00e-03 |  0.734   | 0.762 | 0.562  | 0.585 | 1635014418_Flatten_Dense-2-softmax |
|  40   | 1.00e-03 |  0.734   | 0.762 | 0.559  | 0.583 | 1635014418_Flatten_Dense-2-softmax |
|  45   | 1.00e-03 |  0.734   | 0.756 | 0.557  | 0.582 | 1635014418_Flatten_Dense-2-softmax |
|  49   | 1.00e-03 |  0.741   | 0.756 | 0.555  | 0.581 | 1635014418_Flatten_Dense-2-softmax |
+-------+----------+----------+-------+--------+-------+------------------------------------+

Plot the results.

[9]:

model.plot(path=False)

Strictly speaking, the Perceptron seems to have converged in the right direction.

By reducing the learning rate, all other things being equal, we obtained greater accuracy, lower cost and smoother curves on the plot.

You may have observed something possibly counter-intuitive:

• The cost, which describes the mean difference between output probabilities and labels, is lower for the validation set compared to training set.

• The accuracy, which describes the mean difference between output decisions and labels, is higher for the validation set compared to training set.

While the cost says the error is higher when evaluating on the validation set, the accuracy says the opposite.

That’s because accuracy compares decisions and labels, whereas the cost from the loss function compares probabilities and labels.

For code, maths and pictures behind the Flatten and Dense layers, follow these links:

Let’s take a break and understand the difference in addition to making clear some semantics.

### Difference between accuracy and cost

The question is: Can we expect identical costs for the training and validation set if the accuracy is identical for the training and validation set?

Let’s compare what outputs from the dense layer (A) to the set of sample label (Y).

[10]:

# This is probability distributions for each sample.
print(model.embedding.dtrain.A)
print(model.embedding.dtrain.A.shape)

# These are the labels we target
print(model.embedding.dtrain.Y)
print(model.embedding.dtrain.Y.shape)

[[0.24990897 0.75009103]
[0.15080179 0.84919821]
[0.28627148 0.71372852]
...
[0.09204908 0.90795092]
[0.15813641 0.84186359]
[0.41724774 0.58275226]]
(320, 2)
[[0. 1.]
[0. 1.]
[1. 0.]
...
[1. 0.]
[0. 1.]
[0. 1.]]
(320, 2)

We have probabilities (A) versus binary values (Y).

To compute the accuracy, one needs to convert probabilities to decisions, as well as to retrieve single-digit labels.

[11]:

print(np.argmax(model.embedding.dtrain.A, axis=1))

# Equivalent to calling model.embedding.dtrain.y directly
print(np.argmax(model.embedding.dtrain.Y, axis=1))

[1 1 1 ... 1 1 1]
[1 1 0 ... 0 1 1]

Then, accuracy is computed such as:

[12]:

print ((np.argmax(model.embedding.dtrain.A, axis=1) == model.embedding.dtrain.y))
print ((np.argmax(model.embedding.dtrain.A, axis=1) == model.embedding.dtrain.y).mean())

[ True  True False ... False  True  True]
0.740625

The cost is computed from probabilities, not from decisions. This apart from the fact that accuracy and cost are simply two different functions.

To compute a cost, we first need to compute the loss, which provides information for each single probability in the array (A).

[13]:

# This is the cost. It deals with "true" labels against probabilities

loss = model.training_loss(model.embedding.dtrain.Y, model.embedding.dtrain.A)

print(loss.shape)

(320,)

The cost is a form of average of the loss. Whereas the loss is an array from element-wise comparison between probabilities and labels, the cost is a scalar which is an average per sample, itself an average of the element-wise loss for this sample.

[14]:

print(loss.shape)          # Averaged for each sample
print(loss.mean().shape)   # Average of above - scalar

cost = loss.mean()

print(cost)

(320,)
()
0.5554707080208504

Note that what is fed back in the network during the backward propagation phase is not the loss. It is the derivative of the loss.

[15]:

dloss = model.training_loss(model.embedding.dtrain.Y, model.embedding.dtrain.A, deriv=True)

print(loss)
print(dloss)    # dloss is referred to as dA

[0.2875607  0.16346266 1.2508147  ... 2.38543339 0.17213728 0.53999313]
[[ 0.66658576 -0.66658576]
[ 0.58879069 -0.58879069]
[-1.74659385  1.74659385]
...
[-5.43188494  5.43188494]
[ 0.59392045 -0.59392045]
[ 0.85799753 -0.85799753]]

The loss function and derivatives natively provided with EpyNN can be found in EpyNN/epynn/commons/loss.py.

The metrics natively provided with EpyNN can be found in EpyNN/epynn/commons/metrics.py.

## Recurrent Architectures

Herein, we are going to chain simple schemes based on recurrent architectures.

There are three most commonly cited recurrent layers:

• Recurrent Neural Network (RNN): This is the most simple recurrent layer. It is composed of one to many recurrent units. Each cell performs a single activation which outputs the hidden cell state or simply hidden state.

• Long Short-Term Memory (LSTM): By contrast with the RNN cell, the LSTM cell requires four activations which correspond to three different gates: forget, input (two activations), and output. To compute the hidden cell state, it then requires a fifth activation. Note that in addition to the hidden cell state, there is another so-called cell memory state.

• Gated Recurrent Unit (GRU): Compared to the LSTM cell, the GRU cell has only two gates: reset and update. Practically talking, GRU trains faster than LSTM and is reported to perform better on small datasets or shorter sequences. Both GRU and LSTM, however, are state-of-the-art architectures to deal with sequential data.

See here for more detailed practical descriptions or simply via the pages linked on top of this notebook.

### Embedding

In this example, we use the same setup as for Feed-Forward networks.

[16]:

embedding = Embedding(X_data=X_features,
Y_data=Y_label,
X_encode=True,
Y_encode=True,
relative_size=(2, 1, 0))

We can now chain the simplest schemes to train binary classifiers based on recurrent layers.

### RNN-Dense

The number of RNN units in the RNN layer is set to 1.

[17]:

name = 'RNN-1_Dense-2-softmax'

se_hPars['learning_rate'] = 0.001

rnn = RNN(1)

dense = Dense(2, softmax)

layers = [embedding, rnn, dense]

model = EpyNN(layers=layers, name=name)

Initialize the model.

[18]:

model.initialize(loss='BCE', seed=1, se_hPars=se_hPars.copy(), end='\r')

--- EpyNN Check OK! ---

Train for 50 epochs.

[19]:

model.train(epochs=10, init_logs=False)

Epoch 9 - Batch 0/0 - Accuracy: 0.734 Cost: 0.58678 - TIME: 0.94s RATE: 1.06e+01e/s TTC: 0s

+-------+----------+----------+----------+-------+--------+-------+----------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  BCE   |       |            Experiment            |
|       |   RNN    |  Dense   |  dtrain  | dval  | dtrain | dval  |                                  |
+-------+----------+----------+----------+-------+--------+-------+----------------------------------+
|   0   | 1.00e-03 | 1.00e-03 |  0.544   | 0.581 | 0.676  | 0.659 | 1635014422_RNN-1_Dense-2-softmax |
|   1   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.648  | 0.630 | 1635014422_RNN-1_Dense-2-softmax |
|   2   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.629  | 0.610 | 1635014422_RNN-1_Dense-2-softmax |
|   3   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.615  | 0.595 | 1635014422_RNN-1_Dense-2-softmax |
|   4   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.605  | 0.585 | 1635014422_RNN-1_Dense-2-softmax |
|   5   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.598  | 0.577 | 1635014422_RNN-1_Dense-2-softmax |
|   6   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.593  | 0.571 | 1635014422_RNN-1_Dense-2-softmax |
|   7   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.589  | 0.566 | 1635014422_RNN-1_Dense-2-softmax |
|   8   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.587  | 0.563 | 1635014422_RNN-1_Dense-2-softmax |
|   9   | 1.00e-03 | 1.00e-03 |  0.734   | 0.762 | 0.585  | 0.560 | 1635014422_RNN-1_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+----------------------------------+

You may already note that results are virtually identical to just using a basic Perceptron, although slightly better.

[20]:

model.plot(path=False)

While the y-scale on the plot is a bit misleading when looking at the accuracy, there is no overfitting in there because the BCE cost is the same for both training and validation set at the end of the regression.

For code, maths and pictures behind the RNN layer, follow this link:

### LSTM-Dense

Let’s now proceed with an LSTM layer composed of the 1 unit, all other things being equal.

[21]:

name = 'LSTM-1_Dense-2-softmax'

se_hPars['learning_rate'] = 0.005

lstm = LSTM(1)

dense = Dense(2, softmax)

layers = [embedding, lstm, dense]

model = EpyNN(layers=layers, name=name)

Initialize the model.

[22]:

model.initialize(loss='BCE', seed=1, se_hPars=se_hPars.copy(), end='\r')

--- EpyNN Check OK! ---

Train for 50 epochs.

[23]:

model.train(epochs=10, init_logs=False)

Epoch 9 - Batch 0/0 - Accuracy: 0.734 Cost: 0.57893 - TIME: 0.97s RATE: 1.03e+01e/s TTC: 0s

+-------+----------+----------+----------+-------+--------+-------+-----------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  BCE   |       |            Experiment             |
|       |   LSTM   |  Dense   |  dtrain  | dval  | dtrain | dval  |                                   |
+-------+----------+----------+----------+-------+--------+-------+-----------------------------------+
|   0   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.586  | 0.563 | 1635014423_LSTM-1_Dense-2-softmax |
|   1   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.580  | 0.552 | 1635014423_LSTM-1_Dense-2-softmax |
|   2   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.550 | 1635014423_LSTM-1_Dense-2-softmax |
|   3   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   4   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   5   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   6   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   7   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   8   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
|   9   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014423_LSTM-1_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+-----------------------------------+

The accuracy metrics are simply identical to what we have seen with a simple RNN, which is much faster to compute. It is not significantly better than what we obtained from a simple Perceptron, itself way faster to compute than the RNN based network.

[24]:

model.plot(path=False)

By contrast with the RNN-based network, we observe here a slight overfitting because the cost is lower for the training dataset compared to the validation dataset.

For code, maths and pictures behind the LSTM layer, follow this link:

### GRU-Dense

Let’s now proceed with a GRU layer, all other things being equal.

[25]:

name = 'GRU-1_Dense-2-softmax'

se_hPars['learning_rate'] = 0.005

gru = GRU(1)

flatten = Flatten()

dense = Dense(2, softmax)

layers = [embedding, gru, dense]

model = EpyNN(layers=layers, name=name)

Initialize the network.

[26]:

model.initialize(loss='BCE', seed=1, se_hPars=se_hPars.copy(), end='\r')

--- EpyNN Check OK! ---

Train for 50 epochs.

[27]:

model.train(epochs=10, init_logs=False)

Epoch 9 - Batch 0/0 - Accuracy: 0.734 Cost: 0.57872 - TIME: 1.12s RATE: 8.93e+00e/s TTC: 0s

+-------+----------+----------+----------+-------+--------+-------+----------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  BCE   |       |            Experiment            |
|       |   GRU    |  Dense   |  dtrain  | dval  | dtrain | dval  |                                  |
+-------+----------+----------+----------+-------+--------+-------+----------------------------------+
|   0   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.583  | 0.559 | 1635014424_GRU-1_Dense-2-softmax |
|   1   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.551 | 1635014424_GRU-1_Dense-2-softmax |
|   2   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.550 | 1635014424_GRU-1_Dense-2-softmax |
|   3   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   4   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   5   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   6   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   7   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   8   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
|   9   | 5.00e-03 | 5.00e-03 |  0.734   | 0.762 | 0.579  | 0.549 | 1635014424_GRU-1_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+----------------------------------+

Plot the results.

[28]:

model.plot(path=False)

Overall, and using this dummy dataset made of string features, there is no significant metrics/cost difference from the simple Perceptron to recurrent RNN, GRU and LSTM. In this situation, one would favor the simple Perceptron because it computes faster. At least, it is important to note that the best architecture is not the fanciest, but simply the one that suits your needs and resources.

For code, maths and pictures behind the GRU layer, follow this link:

A trained model can be written on disk such as:

[29]:

model.write()

# model.write(path=/your/custom/path)

Make: /media/synthase/beta/EpyNN/epynnlive/dummy_string/models/1635014424_GRU-1_Dense-2-softmax.pickle

A model can be read from disk such as:

[30]:

model = read_model()

We can retrieve new features and predict on them.

[31]:

X_features, _ = prepare_dataset(N_SAMPLES=10)

dset = model.predict(X_features, X_encode=True)

Results can be extracted such as:

[32]:

for n, pred, probs in zip(dset.ids, dset.P, dset.A):
print(n, pred, probs)

0 1 [0.27207978 0.72792022]
1 1 [0.26511927 0.73488073]
2 1 [0.26579407 0.73420593]
3 1 [0.26865469 0.73134531]
4 1 [0.26554721 0.73445279]
5 1 [0.2699316 0.7300684]
6 1 [0.26448517 0.73551483]
7 1 [0.26460705 0.73539295]
8 1 [0.26701639 0.73298361]
9 1 [0.26556502 0.73443498]


text:
prev ( testsuite > ErrorHandling > NumChildren > mrootE2  ) next (show test run result)

 Alternatives: (mml file)  (full) (simple) (plain) (form) (slideshow) File: ErrorHandling/NumChildren/mrootE2 CVS-ID: Author: Robert Miner and Jeff Schaefer, Geometry Technologies Description: There should be an error unless has exactly two children. Of course, it could be more friendly than the one shown below... passed (p) failed (f) not-tested (n) broken-test (b) some parts pass (s) Sample Rendering: N/A

$\text{exception 25:}\text{exception 25:}$

Source Code:

```
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mroot>
<mn>3</mn>
<mi>x</mi>
<mn>2</mn>
</mroot>
<mroot>
<mn>3</mn>
</mroot>
</mrow>
[/itex]
```

format: plain


text:
I’ve been seeing /dev/sda1: clean followed by {x} files, {n} blocks from a long time, and every time I boot my system, the message appears.

There was a time when the screen used to get stuck at this point and I had to restart my system and press Enter key number of times so that the message can be skipped, and I can login. I got used to this habit of pressing Enter key. Never tried fixing the problem. Never bothered googling what’s the matter. It didn’t seem important to me. I’m lazy.

I cleaned up my system recently, but before that, I also had an issue and it used to appear along with the above message. The screen used to get filled with ^[[5~

/dev/sda1: clean {x} files, {n} blocks

^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~
^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~
^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~^[[5~

• Two things

• Even after using Ubuntu for such a long time, I had no idea what was happening.

• After the fresh installation, the message didn’t disappear.

• Note: I solved the keypress issue by disabling the PageUp key, forever.

I think my laptop’s keyboard has some fault, but I’m not totally sure about it.

Coming back to the real issue - I googled the problem and stumbled upon this question on Ask Ubuntu. The OP had the same issue.

One of the comments was -

This is a normal startup message. It lets you know that there are no filesystem errors.

There were some answers which pointed out that the issue is caused by the graphics driver, in their case - it was nvidia.

My system has Intel HD Graphics!

After a couple of days, my system crashed after logging in, and when I was checking the logs, I found out the Xorg had some issue. I don’t exactly remember what the error was, but after checking the crash reports, I saw

Xorg crashed with SIGABRT in OsAbort()?

I tried to fix it by doing (reinstalling the input drivers) -

sudo apt-get install --reinstall xserver-xorg-input-all

Next day, when I switched on the laptop, I wasn’t able to type the password. At first, I thought the problem is in my external keyboard, so I unplugged it, but this didn’t solve the problem.

I switched on and off my laptop several times hoping that somehow the problem will get fixed (hello?), but there was no luck!

Attempt 1

• Press Ctrl + Alt + F1

• Run sudo apt update && sudo apt upgrade

Problem

Login screen was completely blank. No prompt to enter username and password.

Attempt 2

I stumbled upon this blog post, which said

• Go to the GRUB menu

• Edit the boot option

• Insert /bin/bash before $vt_handoff in linux /boot/vmlinuz-4.18.0-25-generic root=UUID=a98c605-2ac4-4ee3-8070-2560255293fe ro quiet splash$vt_handoff

• Run sudo apt-get install xserver-xorg-input-all

Problem

The solution didn’t work. Pressing Ctrl + Alt + F1 was useless, because again, nothing appeared!

Attempt 3

This worked for me!

I didn’t try to read other answers. Wanted to try my luck.

• Booted into Recovery Mode

• Enabled networking

• Selected repair broken packages

• Resume normal boot.

Issue Fixed!

I don’t exactly remember, but packages related to Xorg were broken. dpkg fixed it.