Reg. Pandas factorize()
From the documnetation


  Encode the object as an enumerated type or categorical variable.
  
  This method is useful for obtaining a numeric representation of an
  array when all that matters is identifying distinct values. factorize
  is available as both a top-level function pandas.factorize(), and as a
  method Series.factorize() and Index.factorize().


The examples section goes on to show that the output of the factorize method actually returns two things:


labels - referring to the new values for each of your classes
uniques - essentially the mapping back to your original labels


In your line of code:

df['product_name'] = df['product_name'].factorize()[0]


The part at the end: [0] means you are only taking the labels, throwing away the uniques that map back to your input.

If you keep both by making the same line:

df['product_name'], mapping = df['product_name'].factorize()


You could now do the rest of your work and end up with a results column full with the factorised output, you can use this line to get the original values back from those factorized labels:

mapped_back_to_product_name = mapping.take(results)


I suggest reading the documentation to get more information on how best to use the method  :-)