<jupyter_start><jupyter_text>Importing important libraries<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
df=pd.read_csv("C:/Users/KIIT/Downloads/Github/Wine/winequality.csv")
df.head(10)#1st 10  rows
df.tail(10)#last 10 rows<jupyter_output><empty_output><jupyter_text>Getting information from the dataset.<jupyter_code>print('Number of rows in the dataset: {}.'.format(df.shape[0]))
print('Number of columns in the dataset: {}.'.format(df.shape[1]))
df.info()
df.isnull().sum()#checking missing values<jupyter_output><empty_output><jupyter_text>As there are missing values and their quantity is very low so we can drop them<jupyter_code>df=df.dropna()
print('Number of rows in the dataset after the rows with missing values were removed: {}.\n{} rows were removed.'
      .format(df.shape[0], 6497-df.shape[0]))
df.isnull().sum()
df.describe().T
df1=df.copy()
quality_map = { 3 : "Low",4 : "Low",5: "Medium",6 : "Medium",7: "Medium",8 : "High",9 : "High"}
df1["quality"] =  df1["quality"].map(quality_map)
df1.head()
cat_map = { "Low":0, "Medium":1, "High":2}
df1["quality"] =  df1["quality"].map(cat_map)
df1.tail()<jupyter_output><empty_output><jupyter_text>Exploratory Data Analysis(EDA) and Data Preprocessing<jupyter_code>plt.figure(figsize=(20,20))
sns.boxplot(data=df)
plt.title('Data Distribution', size=20, y=1.02)
plt.show()<jupyter_output><empty_output><jupyter_text>From the above we can see there are many outliers in the given dataset especially in the columns residual sugar, free sulfur dioxide, total sulfur dioxide.So, we remove them to improve model accuracy.<jupyter_code>cols = ['residual sugar', 'free sulfur dioxide', 'total sulfur dioxide']

for c in cols:
    upper_level = df1[c].mean() + 3*df1[c].std()
    lower_level = df1[c].mean() - 3*df1[c].std()
    df1 = df1[(df1[c] > lower_level) & (df1[c] < upper_level)]

print('Number of rows in the dataset after outliers were removed: {}.\n{} rows were removed.'
      .format(df1.shape[0], 6463-df1.shape[0]))
plt.figure(figsize=(20,20))
sns.boxplot(data=df1)
plt.title('Data Distribution after cleaning')
plt.show()
plt.figure(figsize=(10,10))
sns.countplot(df['type'])<jupyter_output>C:\Users\KIIT\anaconda3\lib\site-packages\seaborn\_decorators.py:43: FutureWarning: Pass the following variable as a keyword arg: x. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>From the above we can see the dataset has more info about white wine than red wine.<jupyter_code>df1.columns
features=['fixed acidity', 'volatile acidity', 'citric acid',
       'residual sugar', 'chlorides', 'free sulfur dioxide',
       'total sulfur dioxide', 'density', 'pH', 'sulphates','alcohol']
for c in features:
    plt.figure(figsize=(10,7))
    sns.barplot(y=c, x='quality',hue='type',palette={'red':'red','white':'blue'}, data=df1,ci=None)
    plt.title('{} per quality'.format(c))
    plt.show()<jupyter_output><empty_output><jupyter_text>A few quick observations:  1. The higher the quality mark, the higher the fixed acidity in red wines.  2. The lower the volatile acidity, the higher the quality mark for red wines.  3. The higher the citric acid, the better quality mark for red wines.  4. The higher the residual sugar, the lower the quality for white wines.  5. The lower the chlorides, the better the quality mark regardless of type of wine.  6. The lower the free sulfur dioxide, the better the quality mark for red wines.  7. The lower the total sulfur dioxide, the better the quality mark regardless of type of wine.  8. The density and pH are pretty much consistant for all qualities and types of wine.  9. The higher the sulphates in red wine, the better the quality mark. 10. The higher the alcohol, the better the quality mark regardless of type of wine.<jupyter_code>df2=df1.drop('quality',axis=1)
plt.figure(figsize=(10,10))
sns.heatmap(df2.corr(),annot=True,cmap="RdYlGn")<jupyter_output><empty_output><jupyter_text>From the above we can see the correlations between different contents of wine.<jupyter_code>df1.head()
df2.head()
type_map={'white':10,'red':11}
df2['type']=df2['type'].map(type_map)
df2.head()
df_red=df2.query('type==11')
df_red
#Red wine description
df_red.describe().T
df_white=df2.query('type==10')
df_white
#white wine description
df_white.describe().T<jupyter_output><empty_output><jupyter_text>Now lets train our quality prediction model using ML<jupyter_code>#Splitting the dataset into train and test set
X=df2.drop('type',axis=1)
y=df2['type']
from sklearn.model_selection import train_test_split
X_train,x_test,y_train,y_test=train_test_split(X,y,random_state=42,test_size=0.3)
#Imoprting our desired model.
#Here I've used logistic regression as the wine type has binary value(either red or white) i.e.
#10 for white wine and 11 for red wine
from sklearn.linear_model import LogisticRegression
model=LogisticRegression(random_state=42)
#training our model
model.fit(X_train,y_train)
#Getting accuracy of model
score=model.score(x_test,y_test)
print(f"Accuracy of logistic regression model is {score*100:.2f}%")
#Predicting values
y_pred=model.predict(x_test)
y_pred[:10]
y_test[:10]<jupyter_output><empty_output><jupyter_text>From y_test and y_pred we can see the model's prediction is pretty good!!<jupyter_code>#Checing model's metrics
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score
print(f"MAE of logistic regression model is {mean_absolute_error(y_test,y_pred):.2f}")
print(f"R2_score of logistic regression model is {r2_score(y_test,y_pred):.2f}")<jupyter_output>MAE of logistic regression model is 0.02
R2_score of logistic regression model is 0.91<jupyter_text>We can see the mean absolute error is 0.02 (very low) and the R2_score is 0.91 which is high.Thus we can say we've got a pretty good model here with accuracy of 98%  Saving the ML model<jupyter_code>import pickle
pickle.dump(model,open('typemodel.sav','wb'))<jupyter_output><empty_output><jupyter_text>Thus our type prediction model is saved as typemodel.sav.We'll use this by loading it in a pyhton script to predict values  Now, lets create the model for quality prediction using neural networks.<jupyter_code>P=df1.drop('type',axis=1)
P
#Getting train and test data
df_train=P.sample(frac=0.7,random_state=42)
df_valid=P.drop(df_train.index)
df_train
df_valid
#Making the data into proper train and test sets to feed into the NN.
Xn_train = df_train.drop('quality', axis=1)
Xn_valid = df_valid.drop('quality', axis=1)
from keras.utils import to_categorical
yn_train = to_categorical(df_train['quality'])
yn_valid = to_categorical(df_valid['quality'])
Xn_train.shape
yn_train<jupyter_output><empty_output><jupyter_text>Creating our NN model using keras<jupyter_code>from tensorflow import keras
from tensorflow.keras import layers
from keras.optimizers import SGD,RMSprop,Adam

#defining our optimisers by defining a learning rate.
opt1=SGD(lr=0.01,momentum=0.9)
opt2=RMSprop(lr=0.01)
opt3=Adam(lr=0.01)

#Creating our model with 4 hidden layers and 1 output layer with each layer having 1024units
mdl=keras.Sequential([
    layers.BatchNormalization(input_shape=[11]),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(rate=0.3),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(rate=0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(rate=0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(rate=0.3),
    layers.BatchNormalization(),
    layers.Dense(3,activation='softmax'),
])

#Adding features to our model
mdl.compile(
     optimizer='adam',#or opt1 or opt2 or opt3.I've used  after testing as it gives best result.
    loss='categorical_crossentropy',#since it is the best classification loss evaluation metrics
    metrics=['accuracy']#since we're doing classification we need to check the model's accuracy
)

#Creating early stopping to stop training to prevent overfitting
from tensorflow.keras.callbacks import EarlyStopping

early_stopping = EarlyStopping(
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=20, # how many epochs to wait before stopping
    restore_best_weights=True,
)
#Fitting/Trainig our created model
new_history = mdl.fit(
    Xn_train, yn_train,
    validation_data=(Xn_valid, yn_valid),
    batch_size=100,
    epochs=500,
    callbacks=[early_stopping], # put your callbacks in a list
    verbose=0,  # turn off training log
)

new_history_df = pd.DataFrame(new_history.history)
new_history_df.loc[:, ['loss', 'val_loss']].plot();
new_history_df.loc[:, ['accuracy', 'val_accuracy']].plot();
print("Minimum validation loss: {:.3f}".format(new_history_df['val_loss'].min()))
print("Maximum validation accuracy: {:.3f}".format(new_history_df['val_accuracy'].max()))
final_Xdata=P.drop('quality',axis=1)
final_ydata=P['quality']
final_ydata=to_categorical(final_ydata)
_, accuracy = mdl.evaluate(final_Xdata,final_ydata,batch_size=50, verbose=0)
print(f"The accuracy of our model is {accuracy*100 :.2f}%")<jupyter_output>The accuracy of our model is 93.34%<jupyter_text>Saving our quality prediction DL model<jupyter_code>mdl.save("qualitymodel.h5")<jupyter_output><empty_output><jupyter_text>Thus our DL model is saved as qualitymodel.h5We'll use this by loading it in a pyhton script to predict values.  Making predictions using our ML (typeprediction) and DL (qualityprediciton) model.<jupyter_code>def predictions(x):
    labels={"Low":0, "Medium":1, "High":2,'white':10,'red':11}
    quality_pred=np.argmax(mdl.predict(x),axis=-1)
    type_pred=model.predict(x)
    for k,v in labels.items():
        if v==quality_pred  :
            quality=k
        if type_pred==v:
            wine=k
    return [wine,quality]
def ip():
    i1=float(input("Enter fixed acidity content  :"))
    i2=float(input("Enter volatile acidity content :"))
    i3=float(input("Enter citric acid content :"))
    i4=float(input("Enter residual sugar content :"))
    i5=float(input("Enter chlorides content :"))
    i6=float(input("Enter free sulfur dioxide content:"))
    i7=float(input("Enter total sulfur dioxide content:"))
    i8=float(input("Enter density :"))
    i9=float(input("Enter pH :"))
    i10=float(input("Enter sulphates content:"))
    i11=float(input("Enter alcohol content:"))
    inp=pd.DataFrame([i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11],index=[features]).transpose()
    print("Your input is-")
    print(inp)
    pr=predictions(inp)
    print(f"The predicted wine type is : {pr[0]} and its quality is : {pr[1]} ")
ip()
df.query('density==0.9968 and pH ==3.38')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1251503098695773, 'fraction_numerical': 0.026639533808158356, 'mean_word_length': 5.873490146217419, 'pattern_counts': {'":': 6, '<': 59, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '375504', 'license': 'MIT', 'n_tokens_mistral': 3855, 'n_tokens_neox': 3614, 'n_words': 1000, 'path': 'Wine quality classification(DL) and Wine type prediction(ML).ipynb', 'repo_name': 'JokaDPiero/Wine-quality-classification-DL-and-Wine-type-prediction-ML-', 'size': '10811'}